Jpp test-rotations-new
the software that should make you happy
Loading...
Searching...
No Matches
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
17namespace JFIT {}
18namespace JPP { using namespace JFIT; }
19
20namespace 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
I/O manipulators.
General purpose messaging.
#define DEBUG(A)
Message macros.
Definition JMessage.hh:62
Simple fit method based on Powell's algorithm, see reference: Numerical Recipes in C++,...
Definition JSimplex.hh:44
double operator()(const JFunction_t &fit, T __begin, T __end)
Multi-dimensional fit.
Definition JSimplex.hh:71
JModel_t wall
Definition JSimplex.hh:266
JModel_t value
Definition JSimplex.hh:240
static int MAXIMUM_ITERATIONS
maximal number of iterations
Definition JSimplex.hh:237
std::vector< JModel_t > step
Definition JSimplex.hh:241
double result_type
Definition JSimplex.hh:47
int numberOfIterations
Definition JSimplex.hh:242
double operator()(const JFunction_t &fit, T __begin, T __end, const JModel_t &step)
1D fit.
Definition JSimplex.hh:178
static double EPSILON
maximal distance to minimum
Definition JSimplex.hh:238
JSimplex()
Default constructor.
Definition JSimplex.hh:55
double evaluate(const JFunction_t &fit, T __begin, T __end) const
Evaluate chi2 for given data set.
Definition JSimplex.hh:253
JModel_t p1
Definition JSimplex.hh:265
JModel_t p0
Definition JSimplex.hh:264
Auxiliary classes and methods for linear and iterative data regression.
Definition JEnergy.hh:15
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Auxiliary data structure for floating point format specification.
Definition JManip.hh:448
Auxiliary class for handling debug parameter within a class.
Definition JMessage.hh:44
static int debug
debug level (default is off).
Definition JMessage.hh:45