Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
Fit.cpp
Go to the documentation of this file.
1
6#include "Fit.h"
7
8#include <algorithm>
9#include <iostream>
10#include <limits>
11#include <sstream>
12#include <string>
13#include <cmath>
14#include <numeric>
15
16namespace {
17
18void log_fit_diagnostics(const fit_app::FitDiagnostics& d) {
19 std::cout << "[FIT] Minuit diagnostics: ok=" << d.ok
20 << ", has_valid_parameters=" << d.has_valid_parameters
21 << ", has_valid_covar=" << d.has_valid_covar
22 << ", has_posdef_covar=" << d.has_posdef_covar
23 << ", has_accurate_covar=" << d.has_accurate_covar
24 << ", made_posdef=" << d.made_posdef
25 << ", hesse_failed=" << d.hesse_failed
26 << ", reached_call_limit=" << d.reached_call_limit
27 << ", above_max_edm=" << d.above_max_edm
28 << ", fmin=" << d.fmin
29 << ", edm=" << d.edm
30 << ", nfcn=" << d.nfcn
31 << std::endl;
32
33 if (!d.cov_eigs.empty()) {
34 double min_eig = std::numeric_limits<double>::infinity();
35 double max_eig = -std::numeric_limits<double>::infinity();
36 std::size_t non_pos = 0;
37
38 for (double eig : d.cov_eigs) {
39 min_eig = std::min(min_eig, eig);
40 max_eig = std::max(max_eig, eig);
41 if (!(eig > 0.0)) ++non_pos;
42 }
43
44 std::cout << "[FIT] Minuit covariance eigenvalues: min=" << min_eig
45 << ", max=" << max_eig
46 << ", non_positive=" << non_pos
47 << ", cond=" << d.cond_number
48 << std::endl;
49 }
50}
51
52void log_matrix_diagnostics(const std::string& label, const RealMatrix& M) {
53 std::cout << "[FIT] Matrix " << label
54 << " shape=" << M.rows() << "x" << M.cols()
55 << std::endl;
56
57 if (M.rows() == 0 || M.cols() == 0) {
58 std::cout << "[FIT] Matrix " << label << " is empty" << std::endl;
59 return;
60 }
61
62 if (M.rows() != M.cols()) {
63 std::cout << "[FIT] Matrix " << label << " is not square" << std::endl;
64 return;
65 }
66
67 try {
68 RealMatrix sym = 0.5 * (M + M.transpose());
69 EigenSystem eig = sym.eig();
70
71 double min_eig = std::numeric_limits<double>::infinity();
72 double max_eig = -std::numeric_limits<double>::infinity();
73 std::size_t non_pos = 0;
74 std::size_t tiny = 0;
75
76 for (std::size_t i = 0; i < eig.D.rows(); ++i) {
77 const double lambda = eig.D.at(i, i);
78 min_eig = std::min(min_eig, lambda);
79 max_eig = std::max(max_eig, lambda);
80 if (!(lambda > 0.0)) ++non_pos;
81 if (std::abs(lambda) < 1e-12) ++tiny;
82 }
83
84 std::cout << "[FIT] Matrix " << label
85 << " eig_min=" << min_eig
86 << ", eig_max=" << max_eig
87 << ", non_positive=" << non_pos
88 << ", tiny(|eig|<1e-12)=" << tiny
89 << std::endl;
90 } catch (const std::exception& e) {
91 std::cout << "[FIT] Matrix " << label
92 << " diagnostics failed: " << e.what()
93 << std::endl;
94 }
95}
96
97RealMatrix invert_or_throw(const RealMatrix& M, const std::string& label) {
98 log_matrix_diagnostics(label, M);
99 try {
100 return M.inv();
101 } catch (const std::exception& e) {
102 std::ostringstream oss;
103 oss << "Failed to invert " << label << ": " << e.what();
104 throw std::runtime_error(oss.str());
105 }
106}
107
108ProfilerMode to_profiler_mode(ProfileBackend b) {
109 switch (b) {
114 default:
116 }
117}
118
119} // namespace
120
121namespace {
122
123std::vector<std::size_t> make_fixed_p_indices(std::size_t p_dim) {
124 std::vector<std::size_t> idx(p_dim);
125 std::iota(idx.begin(), idx.end(), 0);
126 return idx;
127}
128
129void fill_nan_profile_errors(FitResult& fr, std::size_t p_dim) {
130 const double qnan = std::numeric_limits<double>::quiet_NaN();
131 fr.p_hat_std.assign(p_dim, qnan);
132 fr.p_hat_correlations = RealMatrix(p_dim, p_dim);
133 for (std::size_t i = 0; i < p_dim; ++i) {
134 for (std::size_t j = 0; j < p_dim; ++j) {
135 fr.p_hat_correlations.at(i, j) = qnan;
136 }
137 }
138}
139
140void fill_profile_result_from_cov(const RealMatrix& cov_prof, FitResult& fr, std::size_t p_dim) {
141 fr.p_hat_std.resize(p_dim);
142 fr.p_hat_correlations = RealMatrix(p_dim, p_dim);
143
144 for (std::size_t i = 0; i < p_dim; ++i) {
145 fr.p_hat_std[i] = std::sqrt(std::max(0.0, cov_prof.at(i, i)));
146 }
147
148 for (std::size_t i = 0; i < p_dim; ++i) {
149 for (std::size_t j = 0; j < p_dim; ++j) {
150 const double si = fr.p_hat_std[i];
151 const double sj = fr.p_hat_std[j];
152 fr.p_hat_correlations.at(i, j) =
153 (si > 0.0 && sj > 0.0) ? cov_prof.at(i, j) / (si * sj) : 0.0;
154 }
155 }
156}
157
158double choose_profile_fd_step(const fit_app::ParameterDefinition& def,
159 double x,
160 double step_scale)
161{
162 double h = step_scale * fit_app::safe_step(x, def.step_hint);
163
164 if (def.limits.has_value()) {
165 const auto [lo, hi] = def.limits.value();
166 const double dist_lo = x - lo;
167 const double dist_hi = hi - x;
168 const double max_sym = 0.45 * std::max(0.0, std::min(dist_lo, dist_hi));
169 if (max_sym > 0.0) {
170 h = std::min(h, max_sym);
171 }
172 }
173
174 if (!std::isfinite(h) || h <= 0.0) {
175 h = 0.0;
176 }
177 return h;
178}
179
180RealMatrix regularize_spd(const RealMatrix& H, double rel_floor) {
181 RealMatrix sym = 0.5 * (H + H.transpose());
182 EigenSystem eig = sym.eig();
183
184 double max_pos_eig = 0.0;
185 double min_eig = std::numeric_limits<double>::infinity();
186
187 for (std::size_t i = 0; i < eig.D.rows(); ++i) {
188 const double ev = eig.D.at(i, i);
189 min_eig = std::min(min_eig, ev);
190 if (ev > 0.0) {
191 max_pos_eig = std::max(max_pos_eig, ev);
192 }
193 }
194
195 if (!(max_pos_eig > 0.0)) {
196 std::ostringstream oss;
197 oss << "Numerical profile Hessian is not locally convex "
198 << "(all eigenvalues <= 0, min_eig=" << min_eig << ").";
199 throw std::runtime_error(oss.str());
200 }
201
202 const double floor = std::max(1e-10, rel_floor * max_pos_eig);
203
204 RealMatrix Dreg(eig.D.rows(), eig.D.cols());
205 for (std::size_t i = 0; i < eig.D.rows(); ++i) {
206 const double ev = eig.D.at(i, i);
207 Dreg.at(i, i) = (ev > floor) ? ev : floor;
208 }
209
210 return eig.P * Dreg * eig.P.transpose();
211}
212
213double profiled_nll_at(const fit_app::IFitBackend& minimizer,
214 const fit_app::IObjectiveFunction& objective,
215 const std::vector<fit_app::ParameterDefinition>& defs,
216 const std::vector<double>& theta_anchor,
217 std::size_t p_dim,
218 const std::vector<double>& p_fixed,
219 const fit_app::FitOptions& profile_opt)
220{
221 if (defs.size() == p_dim) {
222 if (p_fixed.size() != p_dim) {
223 throw std::invalid_argument(
224 "Profile point dimension does not match the fit-parameter dimension."
225 );
226 }
227
228 const double direct = objective(p_fixed);
229 if (!std::isfinite(direct)) {
230 throw std::runtime_error(
231 "Direct profile evaluation returned a non-finite value."
232 );
233 }
234 return direct;
235 }
236
237 std::vector<fit_app::ParameterDefinition> local_defs = defs;
238 for (std::size_t i = 0; i < local_defs.size(); ++i) {
239 local_defs[i].value = theta_anchor[i];
240 }
241 for (std::size_t i = 0; i < p_dim; ++i) {
242 local_defs[i].value = p_fixed[i];
243 }
244
245 const std::vector<std::size_t> fixed_idx = make_fixed_p_indices(p_dim);
246
248 minimizer.minimize_with_fixed(objective, local_defs, profile_opt, fixed_idx, p_fixed);
249
251 throw std::runtime_error("Profile minimization failed while building fallback Hessian.");
252 }
253
254 return prof.diagnostics.fmin;
255}
256
257double stabilize_profile_step_1d(const fit_app::IFitBackend& minimizer,
258 const fit_app::IObjectiveFunction& objective,
259 const std::vector<fit_app::ParameterDefinition>& defs,
260 const std::vector<double>& theta_hat,
261 std::size_t p_dim,
262 std::size_t i,
263 double h0,
264 const fit_app::FitOptions& profile_opt,
265 double f0)
266{
267 double h = h0;
268 const std::vector<double> p_hat(theta_hat.begin(), theta_hat.begin() + p_dim);
269
270 for (int iter = 0; iter < 8; ++iter) {
271 auto p_plus = p_hat;
272 auto p_minus = p_hat;
273 p_plus[i] += h;
274 p_minus[i] -= h;
275
276 const double f_plus =
277 profiled_nll_at(minimizer, objective, defs, theta_hat, p_dim, p_plus, profile_opt);
278 const double f_minus =
279 profiled_nll_at(minimizer, objective, defs, theta_hat, p_dim, p_minus, profile_opt);
280
281 const double d2 = (f_plus - 2.0 * f0 + f_minus) / (h * h);
282
283 // Accept a local finite-difference step only when the diagonal
284 // curvature is positive and the +/-h probe points do not improve
285 // the central value beyond numerical noise.
286 if (d2 > 0.0 && f_plus >= f0 - 1e-8 && f_minus >= f0 - 1e-8) {
287 return h;
288 }
289
290 h *= 0.5;
291 if (!(h > 0.0)) break;
292 }
293
294 return h;
295}
296
297RealMatrix numerical_profile_hessian(const fit_app::IFitBackend& minimizer,
298 const fit_app::IObjectiveFunction& objective,
299 const std::vector<fit_app::ParameterDefinition>& defs,
300 const std::vector<double>& theta_hat,
301 std::size_t p_dim,
302 const fit_app::FitOptions& profile_opt,
303 double step_scale,
304 double f0)
305{
306 RealMatrix H(p_dim, p_dim);
307
308 std::vector<double> p_hat(theta_hat.begin(), theta_hat.begin() + p_dim);
309 std::vector<double> h(p_dim, 0.0);
310
311 for (std::size_t i = 0; i < p_dim; ++i) {
312 double h0 = choose_profile_fd_step(defs[i], p_hat[i], step_scale);
313 if (!(h0 > 0.0)) {
314 std::ostringstream oss;
315 oss << "Cannot build profile Hessian: initial step collapsed for parameter "
316 << defs[i].name;
317 throw std::runtime_error(oss.str());
318 }
319
320 h[i] = stabilize_profile_step_1d(
321 minimizer, objective, defs, theta_hat, p_dim, i, h0, profile_opt, f0
322 );
323
324 if (!(h[i] > 0.0)) {
325 std::ostringstream oss;
326 oss << "Cannot build profile Hessian: stabilized step collapsed for parameter "
327 << defs[i].name;
328 throw std::runtime_error(oss.str());
329 }
330 }
331
332 for (std::size_t i = 0; i < p_dim; ++i) {
333 auto p_plus = p_hat;
334 auto p_minus = p_hat;
335 p_plus[i] += h[i];
336 p_minus[i] -= h[i];
337
338 const double f_plus =
339 profiled_nll_at(minimizer, objective, defs, theta_hat, p_dim, p_plus, profile_opt);
340 const double f_minus =
341 profiled_nll_at(minimizer, objective, defs, theta_hat, p_dim, p_minus, profile_opt);
342
343 H.at(i, i) = (f_plus - 2.0 * f0 + f_minus) / (h[i] * h[i]);
344
345 for (std::size_t j = i + 1; j < p_dim; ++j) {
346 auto p_pp = p_hat;
347 auto p_pm = p_hat;
348 auto p_mp = p_hat;
349 auto p_mm = p_hat;
350
351 p_pp[i] += h[i]; p_pp[j] += h[j];
352 p_pm[i] += h[i]; p_pm[j] -= h[j];
353 p_mp[i] -= h[i]; p_mp[j] += h[j];
354 p_mm[i] -= h[i]; p_mm[j] -= h[j];
355
356 const double f_pp =
357 profiled_nll_at(minimizer, objective, defs, theta_hat, p_dim, p_pp, profile_opt);
358 const double f_pm =
359 profiled_nll_at(minimizer, objective, defs, theta_hat, p_dim, p_pm, profile_opt);
360 const double f_mp =
361 profiled_nll_at(minimizer, objective, defs, theta_hat, p_dim, p_mp, profile_opt);
362 const double f_mm =
363 profiled_nll_at(minimizer, objective, defs, theta_hat, p_dim, p_mm, profile_opt);
364
365 const double hij = (f_pp - f_pm - f_mp + f_mm) / (4.0 * h[i] * h[j]);
366 H.at(i, j) = hij;
367 H.at(j, i) = hij;
368 }
369 }
370
371 return 0.5 * (H + H.transpose());
372}
373
374} // namespace
375
376MLFitter::MLFitter(std::shared_ptr<LikelihoodContext> ctx, const ModelFn& model, MLFitOptions options)
377 : fit_options_(options)
378{
379 const std::size_t p_dim = ctx->fp_defs.size();
380 this->like_ = std::make_shared<BaseLikelihood>(model, ctx, p_dim);
381}
382
383MLFitter::MLFitter(std::shared_ptr<BaseLikelihood> like, MLFitOptions options)
384 : like_(std::move(like)),
385 fit_options_(options)
386{
387 if (!like_) {
388 throw std::invalid_argument("MLFitter: null likelihood");
389 }
390}
391
392FitResult MLFitter::maximum_likelihood_fit(const std::vector<double>& p0) {
393 const auto defs = like_->get_param_defs();
394 const std::size_t p_dim = p0.size();
395 const std::size_t dim = defs.size();
396
397 std::vector<fit_app::ParameterDefinition> theta0 = defs;
398 for (std::size_t i = 0; i < p_dim; ++i) {
399 theta0[i].value = p0[i];
400 }
401
403 [this](const std::vector<double>& theta) {
404 return like_->nll(theta);
405 },
406 0.5
407 );
408
410 opt.run_hesse = fit_options_.run_hesse;
411 opt.verbose = fit_options_.verbose;
412 if (fit_options_.strategy > 0) {
413 opt.strategy = fit_options_.strategy;
414 }
415 if (fit_options_.max_fcn > 0) {
416 opt.max_fcn = fit_options_.max_fcn;
417 }
418 if (fit_options_.tolerance > 0.0) {
419 opt.tolerance = fit_options_.tolerance;
420 }
421
422#ifdef FIT_APP_HAS_RUN_MINOS
423 opt.run_minos = fit_options_.request_minos;
424#else
425 if (fit_options_.request_minos) {
426 std::cout << "[FIT] MINOS was requested, but fit_app::FitOptions has no run_minos flag in this build.\n"
427 << "[FIT] Define FIT_APP_HAS_RUN_MINOS only if your backend exposes opt.run_minos.\n";
428 }
429#endif
430
431 if (fit_options_.trace_first_evals) {
432 like_->enable_debug_trace(fit_options_.trace_max_evals);
433 } else {
434 like_->disable_debug_trace();
435 }
436
437 std::unique_ptr<fit_app::IFitBackend> minimizer = fit_app::make_minuit_backend();
438 fit_app::BackendFitResult res = minimizer->minimize(f, theta0, opt);
439
440 log_fit_diagnostics(res.diagnostics);
441 log_matrix_diagnostics("Minuit covariance", res.covariance);
442
443 FitResult fr;
444 fr.ell_hat = res.diagnostics.fmin;
445 fr.p_hat.assign(res.values.begin(), res.values.begin() + p_dim);
446 fr.eta_hat.assign(res.values.begin() + p_dim, res.values.end());
447
448 bool have_profile_covariance = false;
449
451 try {
452 RealMatrix H = invert_or_throw(res.covariance, "Minuit covariance");
453
454 RealMatrix H_p_p(p_dim, p_dim);
455 RealMatrix H_p_eta(p_dim, dim - p_dim);
456 RealMatrix H_eta_eta(dim - p_dim, dim - p_dim);
457
458 for (std::size_t i = 0; i < p_dim; ++i) {
459 for (std::size_t j = 0; j < p_dim; ++j) {
460 H_p_p.at(i, j) = H.at(i, j);
461 }
462 }
463
464 for (std::size_t i = 0; i < p_dim; ++i) {
465 for (std::size_t j = p_dim; j < dim; ++j) {
466 H_p_eta.at(i, j - p_dim) = H.at(i, j);
467 }
468 }
469
470 for (std::size_t i = p_dim; i < dim; ++i) {
471 for (std::size_t j = p_dim; j < dim; ++j) {
472 H_eta_eta.at(i - p_dim, j - p_dim) = H.at(i, j);
473 }
474 }
475
476 RealMatrix cov_prof;
477 if (dim == p_dim) {
478 cov_prof = invert_or_throw(H_p_p, "H_p_p (no nuisance block)");
479 } else {
480 RealMatrix H_eta_eta_inv = invert_or_throw(H_eta_eta, "H_eta_eta");
481 RealMatrix H_prof = H_p_p - H_p_eta * H_eta_eta_inv * H_p_eta.transpose();
482 log_matrix_diagnostics("H_prof", H_prof);
483 cov_prof = invert_or_throw(H_prof, "H_prof");
484 }
485
486 fill_profile_result_from_cov(cov_prof, fr, p_dim);
487 have_profile_covariance = true;
488 } catch (const std::exception& e) {
489 std::cout << "[FIT] Failed to build profiled covariance from Minuit covariance: "
490 << e.what() << std::endl;
491 }
492 }
493
494 if (!have_profile_covariance && fit_options_.allow_profile_hessian_fallback) {
495 try {
496 std::cout << "[FIT] Falling back to numerical profile Hessian on fit parameters.\n";
497
498 fit_app::FitOptions profile_opt = opt;
499 profile_opt.run_hesse = false;
500 profile_opt.verbose = false;
501
502 RealMatrix H_prof_num = numerical_profile_hessian(
503 *minimizer,
504 f,
505 defs,
506 res.values,
507 p_dim,
508 profile_opt,
509 fit_options_.profile_hessian_step_scale,
510 res.diagnostics.fmin
511 );
512
513 log_matrix_diagnostics("Numerical profile Hessian", H_prof_num);
514
515 RealMatrix H_prof_reg = regularize_spd(
516 H_prof_num,
518 );
519
520 log_matrix_diagnostics("Regularized numerical profile Hessian", H_prof_reg);
521
522 RealMatrix cov_prof = invert_or_throw(
523 H_prof_reg,
524 "Regularized numerical profile Hessian"
525 );
526
527 fill_profile_result_from_cov(cov_prof, fr, p_dim);
528 have_profile_covariance = true;
529 } catch (const std::exception& e) {
530 std::cout << "[FIT] Numerical profile-Hessian fallback failed: "
531 << e.what() << std::endl;
532 }
533 }
534
535 if (!have_profile_covariance) {
536 std::cout << "[FIT] No covariance could be constructed. Returning MLE with NaN errors.\n";
537 fill_nan_profile_errors(fr, p_dim);
538 }
539
540 this->master_fit_success = res.diagnostics.has_valid_parameters;
541 this->master_fit_result = fr;
542 return fr;
543}
544
545Contour MLFitter::contour(std::size_t x_id, std::size_t y_id, double z,
546 std::array<double, 4> bounds, ContourOptions options) const {
547 if (!this->master_fit_success)
548 LOG_ERROR("InvalidState", "ML fit must have converged before contour computation is available.");
549
550 const bool bad_errors =
551 std::isnan(this->master_fit_result.p_hat_std.at(x_id)) ||
552 std::isnan(this->master_fit_result.p_hat_std.at(y_id));
553
554 if (bad_errors && options.primary_contour_method == ContourAlgorithm::MINUIT) {
555 std::cout << "[FIT] Minuit contour disabled because local covariance is unavailable; "
556 "using fallback method directly.\n";
557 if (options.fallback_contour_method.has_value()) {
559 }
560 }
561
562 ContourConfig cc;
563 cc.fr = this->master_fit_result;
564 cc.x_id = x_id;
565 cc.y_id = y_id;
569 cc.on_progress = options.on_progress;
570 cc.profile_backend = to_profiler_mode(options.profile_backend);
571
572 ContourEngine ce(this->like_, cc);
573 return ce.compute_contour(z, bounds, options.resolution);
574}
std::function< std::vector< double >(const std::vector< double > &p, const std::vector< double > &eta)> ModelFn
Model function signature used by BaseLikelihood.
@ MINUIT
Minuit contour extractor.
High-level maximum-likelihood fitting and confidence-contour API.
ProfileBackend
Backend used to profile nuisance parameters during contour building.
Definition Fit.h:77
#define LOG_ERROR(type,...)
Macro for logging error messages and terminating the application.
Definition Logger.h:41
ProfilerMode
Available algorithms for profiling free parameters.
Definition Profiler.h:25
@ MINUIT
Use the configured numerical minimizer backend.
@ LAPLACE_NUISANCE
Use the Laplace nuisance approximation when possible, with Minuit fallback.
Orchestrates profiled likelihood contour computation.
Contour compute_contour(double z, std::array< double, 4 > bounds, std::size_t resolution)
Computes a profiled 2D contour for a requested significance.
MLFitter(std::shared_ptr< LikelihoodContext > ctx, const ModelFn &model, MLFitOptions options={})
Constructs a fitter from a likelihood context and model function.
Definition Fit.cpp:376
FitResult maximum_likelihood_fit(const std::vector< double > &p0)
Runs the global maximum-likelihood fit.
Definition Fit.cpp:392
Contour contour(std::size_t x_id, std::size_t y_id, double z, std::array< double, 4 > bounds, ContourOptions options) const
Computes a 2D confidence contour after the global fit.
Definition Fit.cpp:545
std::size_t rows() const
Returns the number of rows.
Definition Matrix.cpp:601
EigenSystem eig() const
Computes the eigensystem of a symmetric matrix.
Definition Matrix.cpp:710
double & at(size_t i, size_t j)
Returns a mutable reference to element (i,j) with bounds checking.
Definition Matrix.cpp:587
std::size_t cols() const
Returns the number of columns.
Definition Matrix.cpp:605
RealMatrix transpose() const
Returns the transpose of the matrix.
Definition Matrix.cpp:698
RealMatrix inv() const
Computes the inverse of the matrix via LU decomposition.
Definition Matrix.cpp:750
virtual BackendFitResult minimize_with_fixed(const IObjectiveFunction &objective, const std::vector< ParameterDefinition > &parameters, const FitOptions &options, const std::vector< std::size_t > &fixed_indices, const std::vector< double > &fixed_values) const =0
complex_t h(double s, double m_q, double mu_b)
complex_t H(double z, double r_P)
std::unique_ptr< IFitBackend > make_minuit_backend()
double safe_step(double value, double scale_hint)
Hash specialization for SymbolId<Tag>.
Definition BlockName.h:353
double f(double x)
Wilson special function f depending on x.
Configuration object for ContourEngine.
ProfilerMode profile_backend
Backend used to profile nuisance/free parameters.
ProfilingMethod profiling_method
Profiling strategy used for non-displayed parameters.
ContourProgressCallback on_progress
Optional progress callback invoked during contour computation.
std::size_t x_id
std::size_t y_id
Indices of the two fit parameters displayed on the contour axes.
std::optional< ContourAlgorithm > fallback_contour_method
Optional fallback algorithm if the primary fails.
ContourAlgorithm primary_contour_method
Primary contour extraction algorithm.
FitResult fr
Global fit result used for central values, uncertainties, and correlations.
Runtime options controlling 2D contour computation.
Definition Fit.h:93
ContourProgressCallback on_progress
Definition Fit.h:110
std::size_t resolution
Definition Fit.h:107
ContourAlgorithm primary_contour_method
Definition Fit.h:101
ProfilingMethod profiling_method
Definition Fit.h:95
ProfileBackend profile_backend
Definition Fit.h:98
std::optional< ContourAlgorithm > fallback_contour_method
Definition Fit.h:104
Output of a contour extraction algorithm.
Container for an eigendecomposition.
Definition Matrix.h:489
RealMatrix D
Definition Matrix.h:490
RealMatrix P
Diagonal matrix of eigenvalues.
Definition Matrix.h:491
Summary of a global likelihood fit.
std::vector< double > p_hat_std
Standard deviations of the parameters of interest.
std::vector< double > eta_hat
Nuisance estimates at the global maximum-likelihood point.
std::vector< double > p_hat
Maximum-likelihood estimates for parameters of interest.
RealMatrix p_hat_correlations
Correlation matrix for the parameters of interest.
double ell_hat
Minimum NLL value at the global best-fit point.
Runtime options controlling the global maximum-likelihood fit.
Definition Fit.h:35
unsigned max_fcn
Definition Fit.h:49
bool request_minos
Definition Fit.h:40
unsigned strategy
Definition Fit.h:46
double profile_hessian_eig_floor_rel
Definition Fit.h:64
bool trace_first_evals
Definition Fit.h:67
double profile_hessian_step_scale
Definition Fit.h:61
bool run_hesse
Definition Fit.h:37
std::size_t trace_max_evals
Definition Fit.h:70
bool allow_profile_hessian_fallback
Definition Fit.h:58
double tolerance
Definition Fit.h:52
bool verbose
Definition Fit.h:43
std::vector< double > values
std::optional< std::pair< double, double > > limits