Hyperiso
1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
test_minuit_pipeline.cpp
Go to the documentation of this file.
1
// #include <algorithm>
2
// #include <cassert>
3
// #include <chrono>
4
// #include <cmath>
5
// #include <functional>
6
// #include <iomanip>
7
// #include <iostream>
8
// #include <memory>
9
// #include <stdexcept>
10
// #include <string>
11
// #include <vector>
12
13
// #include "StatisticManager.h"
14
// #include "ObservableInterfaceProxy.h"
15
// #include "StatCorrelationProxy.h"
16
// #include "StatParameterProxy.h"
17
// #include "ObservableInterface.h"
18
// #include "StatParamSourcesProxy.h"
19
// #include "StatDependencyPruner.h"
20
// #include "BaseLikelihood.h"
21
// #include "DefaultNuisancePathsProvider.h"
22
23
// #include "minuit-cpp/FCNBase.hh"
24
// #include "minuit-cpp/FunctionMinimum.hh"
25
// #include "minuit-cpp/MnHesse.hh"
26
// #include "minuit-cpp/MnMigrad.hh"
27
// #include "minuit-cpp/MnUserCovariance.hh"
28
// #include "minuit-cpp/MnUserParameters.hh"
29
// #include "minuit-cpp/MnUserParameterState.hh"
30
31
// #include "BlockProxy.h"
32
// #include "NuisanceReader.h"
33
34
// namespace M2 = MinuitCpp;
35
36
// static void print_vec(const std::vector<double>& vec) {
37
// std::cout << "[ ";
38
// for (size_t i = 0; i < vec.size(); i++) {
39
// std::cout << vec.at(i) << (i == vec.size() - 1 ? " " : ", ");
40
// }
41
// std::cout << "]\n";
42
// }
43
44
45
46
// static double safe_step(double scale) {
47
// double s = std::fabs(scale);
48
// if (!std::isfinite(s) || s <= 0.0) return 1.0;
49
// return 0.1 * s;
50
// }
51
52
// struct MinuitJointFit {
53
// Vector x_hat; // [p, eta]
54
// std::vector<double> x_err;
55
// RealMatrix cov;
56
// double fmin = 0.0;
57
// bool ok = false;
58
// };
59
60
// class GenericFCN final : public M2::FCNBase {
61
// public:
62
// explicit GenericFCN(std::function<double(const std::vector<double>&)> f) : f_(std::move(f)) {}
63
64
// double operator()(const std::vector<double>& x) const override {
65
// const double v = f_(x);
66
// return std::isfinite(v) ? v : 1e300;
67
// }
68
69
// // NLL => Up=0.5
70
// double Up() const override { return 0.5; }
71
72
// private:
73
// std::function<double(const std::vector<double>&)> f_;
74
// };
75
76
// static MinuitJointFit minuit_migrad_hesse(
77
// const std::function<double(const std::vector<double>&)>& f,
78
// const std::vector<double>& x0,
79
// const std::vector<double>& scales,
80
// std::size_t max_fcn,
81
// double tol_edm
82
// ) {
83
// if (x0.size() != scales.size()) {
84
// throw std::invalid_argument(
85
// "x0 and scales must have same size (x0=" + std::to_string(x0.size()) +
86
// ", scales=" + std::to_string(scales.size()) + ")"
87
// );
88
// }
89
90
// GenericFCN fcn(f);
91
92
// M2::MnUserParameters upar;
93
// for (std::size_t i = 0; i < x0.size(); ++i) {
94
// upar.Add("x" + std::to_string(i), x0[i], safe_step(scales[i]));
95
// }
96
97
// M2::MnMigrad migrad(fcn, upar);
98
// M2::FunctionMinimum min = migrad(max_fcn, tol_edm);
99
100
// M2::MnHesse hesse;
101
// hesse(fcn, min);
102
103
// MinuitJointFit out;
104
// out.fmin = min.Fval();
105
// out.ok = min.IsValid();
106
107
// const auto& st = min.UserState();
108
// const std::size_t n = x0.size();
109
110
// out.x_hat.resize(n);
111
// out.x_err.assign(n, 0.0);
112
113
// for (std::size_t i = 0; i < n; ++i) {
114
// out.x_hat[i] = st.Value("x" + std::to_string(i));
115
// out.x_err[i] = st.Error("x" + std::to_string(i));
116
// }
117
118
// out.cov = RealMatrix(n, n);
119
// const auto& cov = st.Covariance();
120
// for (std::size_t i = 0; i < n; ++i)
121
// for (std::size_t j = 0; j < n; ++j)
122
// out.cov.at(i, j) = cov(i, j);
123
124
// return out;
125
// }
126
127
128
// class MinuitMLEstimatorLocal {
129
// public:
130
// // using ModelFn = ProfiledLikelihood::ModelFn;
131
132
// MinuitMLEstimatorLocal(LikelihoodContext ctx, ModelFn model, std::size_t max_fcn, double tol_edm)
133
// : like_(std::move(ctx)), model_(std::move(model)), max_fcn_(max_fcn), tol_edm_(tol_edm) {}
134
135
// FitResult fit_joint(const Vector& p0) const {
136
// const std::size_t p_dim = p0.size();
137
138
// // Vector eta0 = like_.nuisance_central_values;
139
// Vector eta0;
140
// for (auto elem : like_.nuis_defs) {
141
// eta0.push_back(elem.value);
142
// }
143
// Vector eta_scales = like_.nuisance_dist->get_stds();
144
145
// if (eta0.size() != eta_scales.size()) {
146
// std::cerr << "[ERROR] eta0.size() != eta_scales.size(): "
147
// << eta0.size() << " vs " << eta_scales.size() << "\n";
148
// throw std::runtime_error("Nuisance central values and nuisance stds dimensions mismatch");
149
// }
150
151
// std::vector<double> x0;
152
// x0.reserve(p_dim + eta0.size());
153
// x0.insert(x0.end(), p0.begin(), p0.end());
154
// x0.insert(x0.end(), eta0.begin(), eta0.end());
155
156
// Vector p_scales = p0;
157
// for (auto& v : p_scales) v = std::fabs(v);
158
159
// std::vector<double> scales;
160
// scales.reserve(p_scales.size() + eta_scales.size());
161
// scales.insert(scales.end(), p_scales.begin(), p_scales.end());
162
// scales.insert(scales.end(), eta_scales.begin(), eta_scales.end());
163
164
// auto f = [this, p_dim](const std::vector<double>& x) -> double {
165
// Vector p(x.begin(), x.begin() + p_dim);
166
// Vector eta(x.begin() + p_dim, x.end());
167
// return nll(p, eta);
168
// };
169
170
// MinuitJointFit mj = minuit_migrad_hesse(f, x0, scales, max_fcn_, tol_edm_);
171
172
// FitResult fr;
173
// fr.ell_hat = mj.fmin;
174
175
// if (!mj.ok) {
176
// fr.p_hat = p0;
177
// fr.eta_hat = eta0;
178
// fr.p_hat_std = Vector(p_dim, 0.0);
179
// fr.p_hat_correlations = RealMatrix(p_dim, p_dim);
180
// return fr;
181
// }
182
183
// fr.p_hat.assign(mj.x_hat.begin(), mj.x_hat.begin() + p_dim);
184
// fr.eta_hat.assign(mj.x_hat.begin() + p_dim, mj.x_hat.end());
185
186
// RealMatrix cov_p(p_dim, p_dim);
187
// for (std::size_t i = 0; i < p_dim; ++i)
188
// for (std::size_t j = 0; j < p_dim; ++j)
189
// cov_p.at(i, j) = mj.cov.at(i, j);
190
191
// fr.p_hat_std.assign(p_dim, 0.0);
192
// for (std::size_t i = 0; i < p_dim; ++i)
193
// fr.p_hat_std[i] = std::sqrt(std::max(0.0, cov_p.at(i, i)));
194
195
// fr.p_hat_correlations = RealMatrix(p_dim, p_dim);
196
// for (std::size_t i = 0; i < p_dim; ++i) {
197
// for (std::size_t j = 0; j < p_dim; ++j) {
198
// double denom = fr.p_hat_std[i] * fr.p_hat_std[j];
199
// fr.p_hat_correlations.at(i, j) = (denom > 0.0) ? (cov_p.at(i, j) / denom) : 0.0;
200
// }
201
// }
202
203
// return fr;
204
// }
205
206
// private:
207
// double nll(const Vector& p, const Vector& eta) const {
208
// Vector pred = model_(p, eta);
209
210
// Vector r(pred.size());
211
// for (std::size_t i = 0; i < pred.size(); ++i)
212
// r[i] = pred[i] - like_.exp_obs_values[i];
213
214
// double ell_obs = like_.exp_obs_dist->logpdf(r);
215
// double ell_eta = like_.nuisance_dist->logpdf(eta);
216
217
// return -(ell_obs + ell_eta);
218
// }
219
// LikelihoodContext like_;
220
// ModelFn model_;
221
// std::size_t max_fcn_;
222
// double tol_edm_;
223
// };
224
225
226
int
main
(
int
argc,
char
** argv) {
227
228
// auto F_gauss_nll = [](const Vector& p) -> double {
229
// double mu0 = 1e-12, mu1 = 1e3, mu2 = 1e-4;
230
// double s0 = 1e-13, s1 = 1e2, s2 = 1e-6;
231
232
// RealMatrix corr({
233
// {1, 0.2, -0.5},
234
// {0.2, 1, 0.7},
235
// {-0.5, 0.7, 1}
236
// });
237
238
// RealMatrix z({
239
// Vector{(p[0] - mu0) / s0},
240
// Vector{(p[1] - mu1) / s1},
241
// Vector{(p[2] - mu2) / s2}
242
// });
243
244
// return 0.5 * (2 * PI * corr.slogdet().logdet + (z.transpose() * corr.inv() * z).at(0, 0));
245
// };
246
247
// {
248
// std::vector<double> x0 = {3e-12, 250.0, 0.0002};
249
// std::vector<double> scales = {1e-13, 1e2, 1e-6};
250
251
// auto f = [&](const std::vector<double>& x) -> double {
252
// Vector p = {x[0], x[1], x[2]};
253
// return F_gauss_nll(p);
254
// };
255
256
// auto r = minuit_migrad_hesse(f, x0, scales, /*max_fcn*/ 50000, /*tol_edm*/ 1e-10);
257
258
// std::cout << "=== Minuit test (gauss corr) ===\n";
259
// std::cout << "ok=" << r.ok << " fmin=" << std::setprecision(17) << r.fmin << "\n";
260
// std::cout << "xhat = "; print_vec(r.x_hat);
261
// std::cout << "xerr = "; print_vec(r.x_err);
262
// std::cout << "\n";
263
// }
264
265
// HyperisoMaster hyp;
266
// HyperisoConfig config_hyp;
267
// config_hyp.model = Model::SM;
268
// hyp.init("lha/si_input.flha", config_hyp);
269
270
// std::shared_ptr<ObservableInterface> oint = std::make_shared<ObservableInterface>();
271
// oint->add_observable(ObservableMapper::to_id(Observables::BR_BS_MUMU_UNTAG), QCDOrder::LO, true)
272
// .add_observable(ObservableMapper::to_id(Observables::BR_BD_MUMU), QCDOrder::LO, true);
273
274
// StatisticConfig config;
275
// config.MC_draws = 100;
276
// config.MLE_max_iter = 10000;
277
// config.MLE_tol = 1e-6;
278
279
// std::vector<ParamId> p_specs = {
280
// ParamId(ParameterType::WILSON, GroupMapper::str(WGroup::B, ScaleType::MATCHING), WCoefMapper::flha_full(WCoef::C10, QCDOrder::LO, ContributionType::SM))
281
// };
282
283
// std::shared_ptr<IStatParamOptimizerProxy> spop = std::make_shared<StatParamOptimizerProxy>();
284
// auto model = std::make_shared<ObservableInterfaceProxy>(oint, spop);
285
286
// std::shared_ptr<INuisancePathsProvider> npp = std::make_shared<DefaultNuisancePathsProvider>();
287
288
// StatisticManager stat(
289
// config,
290
// model,
291
// std::make_shared<StatCorrelationProxy>(),
292
// std::make_shared<StatParameterProxy>(),
293
// std::make_shared<StatParamSourcesProxy>(),
294
// std::make_shared<StatDependencyPruner>(),
295
// std::make_shared<NuisanceReader>(npp),
296
// spop
297
// );
298
299
// LOG_INFO("YO1");
300
// stat.update_cache(p_specs);
301
302
// BlockProxy bp;
303
// bp.log_all_blocks(ParameterType::WILSON);
304
305
// auto start_u = std::chrono::steady_clock::now();
306
// stat.compute_uncertainties();
307
// auto stop_u = std::chrono::steady_clock::now();
308
// LOG_INFO("YO2");
309
// auto us_u = std::chrono::duration_cast<std::chrono::microseconds>(stop_u - start_u).count();
310
// std::cout << "Uncertainty estimation time : " << us_u << " µs\n";
311
312
313
// stat.update_cache(p_specs);
314
315
// auto p_specs_map = stat.get_p_specs(p_specs);
316
// auto eta_specs_real = stat.get_all_obss_deps();
317
// for (const auto& [pid, _] : p_specs_map) eta_specs_real.erase(pid);
318
// auto exp_obs_map = stat.get_obs_exp();
319
320
// auto unz_p = unzip(p_specs_map);
321
// auto unz_eta = unzip(eta_specs_real);
322
// auto unz_obs = unzip(exp_obs_map);
323
324
// std::vector<ParamId> p_ids = unz_p.ids;
325
// std::vector<ParamId> eta_ids = unz_eta.ids;
326
// std::vector<ExperimentObs> obs_ids = unz_obs.ids;
327
328
// auto nuisance_dist = stat.build_nuisance_distribution();
329
// auto exp_obs_dist = stat.build_exp_data_distribution();
330
331
// if (nuisance_dist->get_stds().size() != unz_eta.vals.size()) {
332
// std::cerr << "[ERROR] nuisance_dist->get_stds().size()=" << nuisance_dist->get_stds().size()
333
// << " but eta central values size=" << unz_eta.vals.size() << "\n";
334
// std::cerr << "=> appelle fill_cache() juste avant de construire ctx et évite de recalculer eta ailleurs.\n";
335
// return 3;
336
// }
337
// if (exp_obs_dist->dim() != unz_obs.vals.size()) {
338
// std::cerr << "[ERROR] exp_obs_dist->dim()=" << exp_obs_dist->dim()
339
// << " but exp obs values size=" << unz_obs.vals.size() << "\n";
340
// return 4;
341
// }
342
343
// LikelihoodContext ctx;
344
// ctx.nuisance_dist = std::move(nuisance_dist);
345
// ctx.exp_obs_dist = std::move(exp_obs_dist);
346
// Vec _ = unz_eta.vals;
347
// // ctx.nuisance_central_values = unz_eta.vals;
348
// ctx.exp_obs_values = unz_obs.vals;
349
350
// auto model_fn = [model, obs_ids, p_ids, eta_ids](const Vec& p_vec, const Vec& eta_vec) -> Vec {
351
// auto pred_map = model->predict_optimized(zip(p_ids, p_vec), zip(eta_ids, eta_vec));
352
353
// Vec out;
354
// out.reserve(obs_ids.size());
355
356
// for (const auto& bid : obs_ids) {
357
// const auto& vec = pred_map.at(bid.obs.s);
358
359
// auto it = std::find_if(vec.begin(), vec.end(), [&](const ObservableValue& ov){
360
// auto bin = ov.bin.value_or(std::pair<double,double>{0.,0.});
361
// return bin == bid.obs.p;
362
// });
363
// if (it == vec.end()) throw std::runtime_error("Missing predicted observable/bin");
364
// out.push_back(it->value);
365
// }
366
// return out;
367
// };
368
369
// auto start_m = std::chrono::steady_clock::now();
370
// MinuitMLEstimatorLocal est(std::move(ctx), model_fn, config.MLE_max_iter, config.MLE_tol);
371
// FitResult fr = est.fit_joint(unz_p.vals);
372
// auto stop_m = std::chrono::steady_clock::now();
373
// auto us_m = std::chrono::duration_cast<std::chrono::microseconds>(stop_m - start_m).count();
374
// std::cout << "MLE (Minuit) fitting time : " << us_m << " µs\n";
375
376
// std::cout << "ell_hat = " << std::setprecision(17) << fr.ell_hat << "\n";
377
378
// std::cout << "p_hat = ";
379
// for (auto v : fr.p_hat) std::cout << v << " ";
380
// std::cout << "\n";
381
382
// std::cout << "p_hat_std = ";
383
// for (auto v : fr.p_hat_std) std::cout << v << " ";
384
// std::cout << "\n";
385
386
// std::cout << "p_hat_correlations:\n" << fr.p_hat_correlations << "\n";
387
388
// // std::cout << *StatParameterProxy(ParameterType::OBSERVABLE)
389
// // .get_param("FOBS", LhaID("511_1_0_0_2_13_-13"))
390
// // << std::endl;
391
392
return
0;
393
}
main
int main()
Definition
test_dynamic_registry.cpp:12
Hyperiso
core
src
Statistic
app
test_minuit_pipeline.cpp
Generated by
1.9.8