Jpp  16.0.2
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JSimplex.hh
Go to the documentation of this file.
1 #ifndef __JFIT__JSIMPLEX__
2 #define __JFIT__JSIMPLEX__
3 
4 #include <cmath>
5 #include <vector>
6 #include <ostream>
7 #include <iomanip>
8 
9 #include "JLang/JManip.hh"
10 #include "Jeep/JMessage.hh"
11 
12 
13 /**
14  * \author mdejong
15  */
16 
17 namespace JFIT {}
18 namespace JPP { using namespace JFIT; }
19 
20 namespace JFIT {
21 
22  using JEEP::JMessage;
23 
24 
25  /**
26  * Simple fit method based on Powell's algorithm, see reference:
27  * Numerical Recipes in C++, W.H. Press, S.A. Teukolsky, W.T. Vetterling and B.P. Flannery,
28  * Cambridge University Press.
29  *
30  * The template argument refers to the model that should be fitted to the data.
31  * This data structure should have arithmetic capabalities.
32  *
33  * The data member JSimplex::value corresponds to the start, current or final value
34  * of the model of the fit procedure.
35  * The data member JSimplex::step corresponds to the step directions.
36  * Note that the step directions may change during the fit.
37  * The template fit function should return the data type JGandalf::result_type
38  * which is composed of the values of the chi2 and gradient of a hit.
39  * The function operator returns the chi2 of the fit.
40  */
41  template<class JModel_t>
42  class JSimplex :
43  public JMessage< JSimplex<JModel_t> >
44  {
45  public:
46 
47  typedef double result_type;
48 
50 
51 
52  /**
53  * Default constructor.
54  */
56  {}
57 
58 
59  /**
60  * Multi-dimensional fit.
61  *
62  * The given fit function should return the equivalent of chi2 for
63  * the current value of the given model and a given data point.
64  *
65  * \param fit fit function
66  * \param __begin begin of data
67  * \param __end end of data
68  * \return chi2
69  */
70  template<class JFunction_t, class T>
71  double operator()(const JFunction_t& fit, T __begin, T __end)
72  {
73  using namespace std;
74  using namespace JPP;
75 
76  double chi2_old = evaluate(fit, __begin, __end);
77 
78  const int N = step.size();
79 
80  if (N != 0) {
81 
82  p0 = value;
83  p1 = value;
84  wall = value;
85 
86  double chi2[N];
87 
89 
91 
92  DEBUG("old: " << FIXED(12,5) << chi2_old << endl);
93 
94  p0 = value;
95 
96  for (int i = 0; i != N; ++i) {
97 
98  DEBUG("step: " << i << ' ' << setw(5) << numberOfIterations << endl);
99 
100  chi2[i] = (*this)(fit, __begin, __end, step[i]);
101  }
102 
103  // overall step direction of last iteration
104 
105  wall = value;
106  wall -= p0;
107 
108  const double chi2_new = (*this)(fit, __begin, __end, wall);
109 
110  DEBUG("new: " << FIXED(12,5) << chi2_new << endl);
111 
112 
113  if (fabs(chi2_old - chi2_new) < EPSILON*fabs(chi2_old)) {
114  return chi2_new;
115  }
116 
117  // double overall step
118 
119  wall = value;
120  wall -= p0;
121  value += wall;
122 
123  const double fe = evaluate(fit, __begin, __end);
124 
125  value -= wall;
126 
127 
128  for (int i = N-1; i != 0; --i) {
129  chi2[i] = chi2[i-1] - chi2[i];
130  }
131 
132  chi2[0] = chi2_old - chi2[0];
133 
134 
135  double df = 0.0;
136 
137  for (int i = 0; i != N; ++i) {
138  if (chi2[i] > df) {
139  df = chi2[i];
140  }
141  }
142 
143  const double fn = chi2_new;
144  const double f0 = chi2_old;
145  const double ff = f0 - fn - df;
146 
147  // shift step directions
148 
149  if (fe < f0 && 2.0*(f0 - 2.0*fn + fe)*ff*ff < (f0-fe)*(f0-fe)*df) {
150 
151  for (int i = 0; i != N - 1; ++i) {
152  step[i] = step[i+1];
153  }
154 
155  step[N-1] = wall;
156  }
157 
158  chi2_old = chi2_new;
159  }
160  }
161 
162  return chi2_old;
163  }
164 
165 
166  /**
167  * 1D fit.
168  *
169  * The given fit function should return the equivalent of chi2 for
170  * the current value of the given model and a given data point.
171  *
172  * \param fit fit function
173  * \param __begin begin of data
174  * \param __end end of data
175  * \param step step direction
176  */
177  template<class JFunction_t, class T>
178  double operator()(const JFunction_t& fit, T __begin, T __end, const JModel_t& step)
179  {
180  using namespace std;
181  using namespace JPP;
182 
183  double lambda = 0.5; // control parameter
184  double factor = 1.0; // multiplication factor
185 
186  double chi2_old = evaluate(fit, __begin, __end);
187 
188  for (int i = 0; numberOfIterations != MAXIMUM_ITERATIONS; ++numberOfIterations, ++i) {
189 
190  p1 = step;
191  p1 *= lambda;
192  value += p1;
193 
194  const double chi2_new = evaluate(fit, __begin, __end);
195 
196  DEBUG("step: " << setw(3) << i << ' ' << FIXED(12,5) << chi2_old << ' ' << FIXED(12,5) << chi2_new << ' ' << FIXED(5,2) << lambda << endl);
197 
198  if (fabs(chi2_old - chi2_new) < EPSILON*fabs(chi2_old)) {
199 
200  if (chi2_new > chi2_old) {
201 
202  p1 = step;
203  p1 *= lambda;
204  value -= p1; // undo last step
205 
206  return chi2_old;
207 
208  } else {
209 
210  return chi2_new;
211  }
212  }
213 
214  if (chi2_new < chi2_old) {
215 
216  chi2_old = chi2_new;
217 
218  } else {
219 
220  p1 = step;
221  p1 *= lambda;
222  value -= p1; // step back
223  lambda = -lambda; // change direction
224 
225  if (i != 0) {
226  factor = 0.5; // reduce step size
227  }
228  }
229 
230  lambda = factor * lambda;
231  }
232 
233  return chi2_old;
234  }
235 
236 
237  static int MAXIMUM_ITERATIONS; //!< maximal number of iterations
238  static double EPSILON; //!< maximal distance to minimum
239 
240  JModel_t value;
243 
244  private:
245  /**
246  * Evaluate chi2 for given data set.
247  *
248  * \param fit fit function
249  * \param __begin begin of data
250  * \param __end end of data
251  */
252  template<class JFunction_t, class T>
253  inline double evaluate(const JFunction_t& fit, T __begin, T __end) const
254  {
255  double chi2 = 0.0;
256 
257  for (T hit = __begin; hit != __end; ++hit) {
258  chi2 += fit(value, *hit);
259  }
260 
261  return chi2;
262  }
263 
264  mutable JModel_t p0;
265  mutable JModel_t p1;
266  mutable JModel_t wall;
267  };
268 
269 
270  /**
271  * maximal number of iterations.
272  */
273  template<class JModel_t>
275 
276 
277  /**
278  * maximal distance to minimum.
279  */
280  template<class JModel_t>
281  double JSimplex<JModel_t>::EPSILON = 1.0e-4;
282 }
283 
284 #endif
static int debug
debug level (default is off).
Definition: JMessage.hh:45
double operator()(const JFunction_t &fit, T __begin, T __end, const JModel_t &step)
1D fit.
Definition: JSimplex.hh:178
then JShowerPostfit f $INPUT_FILE o $OUTPUT_FILE N
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:446
JModel_t p1
Definition: JSimplex.hh:265
do set_variable OUTPUT_DIRECTORY $WORKDIR T
int numberOfIterations
Definition: JSimplex.hh:242
JModel_t value
Definition: JSimplex.hh:240
General purpose messaging.
I/O manipulators.
double operator()(const JFunction_t &fit, T __begin, T __end)
Multi-dimensional fit.
Definition: JSimplex.hh:71
Simple fit method based on Powell&#39;s algorithm, see reference: Numerical Recipes in C++...
Definition: JSimplex.hh:42
JModel_t p0
Definition: JSimplex.hh:264
JModel_t wall
Definition: JSimplex.hh:266
JSimplex()
Default constructor.
Definition: JSimplex.hh:55
then usage $script< input_file >< detector_file > fi set_variable OUTPUT_DIR set_variable SELECTOR JDAQTimesliceL1 set_variable DEBUG case set_variable DEBUG
double evaluate(const JFunction_t &fit, T __begin, T __end) const
Evaluate chi2 for given data set.
Definition: JSimplex.hh:253
static int MAXIMUM_ITERATIONS
maximal number of iterations
Definition: JSimplex.hh:237
static double EPSILON
maximal distance to minimum
Definition: JSimplex.hh:238
double result_type
Definition: JSimplex.hh:47
Auxiliary class for handling debug parameter within a class.
Definition: JMessage.hh:44
std::vector< JModel_t > step
Definition: JSimplex.hh:241