Jpp 20.0.0-rc.2
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.
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