File indexing completed on 2024-04-06 12:31:17
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #include "TopQuarkAnalysis/TopHitFit/interface/Base_Constrainer.h"
0039 #include "TopQuarkAnalysis/TopHitFit/interface/matutil.h"
0040 #include "TopQuarkAnalysis/TopHitFit/interface/Defaults.h"
0041 #include <iostream>
0042 #include <cmath>
0043 #include <cstdlib>
0044
0045 using std::abort;
0046 using std::abs;
0047 using std::cout;
0048 using std::ostream;
0049
0050
0051
0052
0053
0054 namespace {
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 bool test_different(double a, double b, double c, double eps)
0070
0071
0072
0073
0074
0075 {
0076 double scale = eps * (abs(a) + abs(b) + abs(c));
0077 if (abs(a) != 0 && abs(b) / abs(a) < 0.1 && abs(a) > scale)
0078 scale = abs(a) * .5;
0079 if (scale == 0)
0080 return false;
0081 if (scale < eps)
0082 scale = eps;
0083 return abs(a - b) > scale;
0084 }
0085
0086 }
0087
0088
0089
0090 namespace hitfit {
0091
0092
0093
0094 Base_Constrainer_Args::Base_Constrainer_Args(const Defaults& defs)
0095
0096
0097
0098
0099
0100
0101 : _test_gradient(defs.get_bool("test_gradient")),
0102 _test_step(defs.get_float("test_step")),
0103 _test_eps(defs.get_float("test_eps")) {}
0104
0105 bool Base_Constrainer_Args::test_gradient() const
0106
0107
0108
0109
0110 {
0111 return _test_gradient;
0112 }
0113
0114 double Base_Constrainer_Args::test_step() const
0115
0116
0117
0118
0119 {
0120 return _test_step;
0121 }
0122
0123 double Base_Constrainer_Args::test_eps() const
0124
0125
0126
0127
0128 {
0129 return _test_eps;
0130 }
0131
0132
0133
0134 Constraint_Calculator::Constraint_Calculator(int nconstraints)
0135
0136
0137
0138
0139
0140
0141 : _nconstraints(nconstraints) {}
0142
0143 int Constraint_Calculator::nconstraints() const
0144
0145
0146
0147
0148
0149
0150 {
0151 return _nconstraints;
0152 }
0153
0154
0155
0156 Base_Constrainer::Base_Constrainer(const Base_Constrainer_Args& args)
0157
0158
0159
0160
0161
0162
0163 : _args(args) {}
0164
0165 std::ostream& Base_Constrainer::print(std::ostream& s) const
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 {
0176 s << "Base_Constrainer parameters:\n";
0177 s << " test_gradient: " << _args.test_gradient() << " test_step: " << _args.test_step()
0178 << " test_eps: " << _args.test_eps() << "\n";
0179 return s;
0180 }
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 std::ostream& operator<<(std::ostream& s, const Base_Constrainer& f)
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 {
0203 return f.print(s);
0204 }
0205
0206 bool Base_Constrainer::call_constraint_fcn(Constraint_Calculator& constraint_calculator,
0207 const Column_Vector& x,
0208 const Column_Vector& y,
0209 Row_Vector& F,
0210 Matrix& Bx,
0211 Matrix& By) const
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 {
0235
0236 bool val = constraint_calculator.eval(x, y, F, Bx, By);
0237
0238
0239 if (!_args.test_gradient())
0240 return val;
0241
0242
0243 if (!val)
0244 return false;
0245
0246 int Nw = x.num_row();
0247 int Np = y.num_row();
0248 int Nc = F.num_col();
0249
0250
0251 for (int i = 1; i <= Nc; i++) {
0252
0253 Column_Vector step_x(Nw, 0);
0254 step_x(i) = _args.test_step();
0255 Column_Vector new_x = x + step_x;
0256
0257
0258 Matrix new_Bx(Nw, Nc);
0259 Matrix new_By(Np, Nc);
0260 Row_Vector new_F(Nc);
0261 if (!constraint_calculator.eval(new_x, y, new_F, new_Bx, new_By))
0262 return false;
0263
0264
0265
0266 Row_Vector test_F = F + step_x.T() * Bx;
0267
0268
0269 for (int j = 1; j <= Nc; j++) {
0270 if (test_different(test_F(j), new_F(j), F(j), _args.test_eps())) {
0271 cout << "bad gradient x " << i << " " << j << "\n";
0272 cout << x;
0273 cout << y;
0274 cout << new_x;
0275 cout << F;
0276 cout << new_F;
0277 cout << Bx;
0278 cout << (test_F - new_F);
0279 abort();
0280 }
0281 }
0282 }
0283
0284
0285 for (int i = 1; i <= Np; i++) {
0286
0287 Column_Vector step_y(Np, 0);
0288 step_y(i) = _args.test_step();
0289 Column_Vector new_y = y + step_y;
0290
0291
0292 Matrix new_Bx(Nw, Nc);
0293 Matrix new_By(Np, Nc);
0294 Row_Vector new_F(Nc);
0295 if (!constraint_calculator.eval(x, new_y, new_F, new_Bx, new_By))
0296 return false;
0297
0298
0299
0300 Row_Vector test_F = F + step_y.T() * By;
0301
0302
0303 for (int j = 1; j <= Nc; j++) {
0304 if (test_different(test_F(j), new_F(j), F(j), _args.test_eps())) {
0305 cout << "bad gradient y " << i << " " << j << "\n";
0306 cout << x;
0307 cout << y;
0308 cout << new_y;
0309 cout << F;
0310 cout << new_F;
0311 cout << Bx;
0312 cout << (test_F - new_F);
0313 abort();
0314 }
0315 }
0316 }
0317
0318
0319 return true;
0320 }
0321
0322 }