Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
BaseLikelihood.cpp
Go to the documentation of this file.
1#include "BaseLikelihood.h"
2
3BaseLikelihood::BaseLikelihood(const ModelFn& model, std::shared_ptr<LikelihoodContext> ctx, size_t p_dim) : p_dim(p_dim) {
4 this->ctx = std::move(ctx);
5 this->model = model;
6}
7
8
9void BaseLikelihood::maybe_log_debug_eval(const std::vector<double>& theta,
10 const std::vector<double>& p,
11 const std::vector<double>& eta,
12 const std::vector<double>& res,
13 double ell_obs,
14 double ell_nuis,
15 double nll_value) const
16{
18 return;
19 }
21 return;
22 }
23
25 debug_ref_theta_ = theta;
27 }
29 debug_ref_res_ = res;
31 }
32
33 const double theta_shift = max_abs_diff(theta, debug_ref_theta_);
34 const double res_shift = max_abs_diff(res, debug_ref_res_);
35
36 std::cout << "[FITDBG] eval=" << debug_eval_count_
37 << " nll=" << nll_value
38 << " ell_obs=" << ell_obs
39 << " ell_nuis=" << ell_nuis
40 << " max|theta-theta0|=" << theta_shift
41 << " max|res-res0|=" << res_shift;
42
43 if (!p.empty()) {
44 std::cout << " p=[";
45 for (std::size_t i = 0; i < std::min<std::size_t>(p.size(), 4); ++i) {
46 if (i) std::cout << ", ";
47 std::cout << p[i];
48 }
49 if (p.size() > 4) std::cout << ", ...";
50 std::cout << "]";
51 }
52
53 if (!eta.empty()) {
54 std::cout << " eta=[";
55 for (std::size_t i = 0; i < std::min<std::size_t>(eta.size(), 4); ++i) {
56 if (i) std::cout << ", ";
57 std::cout << eta[i];
58 }
59 if (eta.size() > 4) std::cout << ", ...";
60 std::cout << "]";
61 }
62
63 std::cout << std::endl;
65}
66
67
68double BaseLikelihood::nll(const std::vector<double>& theta) const {
69 std::vector<double> p(theta.begin(), theta.begin() + p_dim);
70 std::vector<double> eta(theta.begin() + p_dim, theta.end());
71
72 try {
73 std::vector<double> res = model(p, eta);
74
75 for (size_t i = 0; i < res.size(); i++) {
76 if (!std::isfinite(res[i])) {
77 return 1e100;
78 }
79 res[i] -= this->ctx->exp_obs_values[i];
80 if (!std::isfinite(res[i])) {
81 return 1e100;
82 }
83 }
84
85 double ell_obs = this->ctx->exp_obs_dist->logpdf(res);
86 double ell_nuis = this->ctx->nuisance_dist->logpdf(eta);
87
88 if (!std::isfinite(ell_obs) || !std::isfinite(ell_nuis)) {
89 return 1e100;
90 }
91
92 double out = -(ell_obs + ell_nuis);
93 if (!std::isfinite(out)) {
94 return 1e100;
95 }
96
97 maybe_log_debug_eval(theta, p, eta, res, ell_obs, ell_nuis, out);
98 return out;
99 }
100 catch (const std::exception& e) {
102 std::cerr << "[FIT DEBUG] model/nll exception: " << e.what() << "\n";
103 }
104 return 1e100;
105 }
106 catch (...) {
108 std::cerr << "[FIT DEBUG] model/nll unknown exception\n";
109 }
110 return 1e100;
111 }
112}
113
114std::size_t BaseLikelihood::dim() const {
115 return this->ctx->nuisance_dist->dim() + this->p_dim;
116}
117
118std::size_t BaseLikelihood::p_dimension() const {
119 return p_dim;
120}
121
122std::size_t BaseLikelihood::eta_dimension() const {
123 return ctx->nuis_defs.size();
124}
125
126std::vector<double> BaseLikelihood::central_p() const {
127 std::vector<double> out;
128 out.reserve(ctx->fp_defs.size());
129
130 for (const auto& def : ctx->fp_defs) {
131 out.push_back(def.value);
132 }
133
134 return out;
135}
136
137std::vector<double> BaseLikelihood::central_eta() const {
138 std::vector<double> out;
139 out.reserve(ctx->nuis_defs.size());
140
141 for (const auto& def : ctx->nuis_defs) {
142 out.push_back(def.value);
143 }
144
145 return out;
146}
147
148std::vector<double> BaseLikelihood::predict(
149 const std::vector<double>& p,
150 const std::vector<double>& eta
151) const {
152 return model(p, eta);
153}
154
155std::vector<double> BaseLikelihood::residuals(
156 const std::vector<double>& p,
157 const std::vector<double>& eta
158) const {
159 std::vector<double> pred = model(p, eta);
160
161 if (pred.size() != ctx->exp_obs_values.size()) {
162 throw std::runtime_error("BaseLikelihood::residuals: prediction/observation size mismatch");
163 }
164
165 for (std::size_t i = 0; i < pred.size(); ++i) {
166 pred[i] -= ctx->exp_obs_values[i];
167 }
168
169 return pred;
170}
171
173 const std::vector<double>& p,
174 const std::vector<double>& eta
175) const {
176 std::vector<double> theta;
177 theta.reserve(p.size() + eta.size());
178 theta.insert(theta.end(), p.begin(), p.end());
179 theta.insert(theta.end(), eta.begin(), eta.end());
180
181 return nll(theta);
182}
183
185 const std::vector<double>& r
186) const {
187 RealMatrix W = ctx->exp_obs_dist->curvature(r);
188
189 for (std::size_t i = 0; i < W.rows(); ++i) {
190 for (std::size_t j = 0; j < W.cols(); ++j) {
191 if (!std::isfinite(W.at(i, j))) {
192 std::cout << "[WOBSDBG] non-finite W_obs("
193 << i << "," << j << ")"
194 << " r_i=" << r[i]
195 << " r_j=" << r[j]
196 << " exp_i=" << ctx->exp_obs_values[i]
197 << " exp_j=" << ctx->exp_obs_values[j]
198 << std::endl;
199 }
200 }
201 }
202
203 return W;
204}
205
207 const std::vector<double>& eta
208) const {
209 return ctx->nuisance_dist->curvature(eta);
210}
Concrete profileable likelihood built from a model and joint distributions.
std::function< std::vector< double >(const std::vector< double > &p, const std::vector< double > &eta)> ModelFn
Model function signature used by BaseLikelihood.
std::shared_ptr< LikelihoodContext > ctx
Shared statistical context used by the likelihood.
std::vector< double > central_eta() const override
Returns the central values of the nuisance parameters.
std::vector< double > central_p() const override
Returns the central values of the fitted parameters.
std::vector< double > predict(const std::vector< double > &p, const std::vector< double > &eta) const override
bool debug_have_ref_theta_
Whether the debug reference parameter vector is set.
std::size_t p_dimension() const override
Returns the dimension of the fitted-parameter block.
RealMatrix nuisance_curvature(const std::vector< double > &eta) const override
RealMatrix observable_curvature(const std::vector< double > &r) const override
std::vector< double > debug_ref_res_
First traced residual vector used as debug reference.
std::size_t debug_trace_max_evals_
Maximum number of traced evaluations.
std::vector< double > residuals(const std::vector< double > &p, const std::vector< double > &eta) const override
bool debug_trace_enabled_
Whether evaluation debug tracing is enabled.
double nll(const std::vector< double > &theta) const override
Evaluates the negative log-likelihood for a full parameter vector.
std::vector< double > debug_ref_theta_
First traced parameter vector used as debug reference.
std::size_t eta_dimension() const override
Returns the dimension of the nuisance-parameter block.
double nll_from_split(const std::vector< double > &p, const std::vector< double > &eta) const override
std::size_t dim() const override
Returns the total likelihood dimension.
ModelFn model
Model function evaluated by the likelihood.
bool debug_have_ref_res_
Whether the debug reference residual vector is set.
std::size_t debug_eval_count_
Number of evaluations already traced.
std::size_t p_dim
Dimension of the fitted-parameter block.
BaseLikelihood(const ModelFn &model, std::shared_ptr< LikelihoodContext > ctx, size_t p_dim)
Constructs a likelihood from a model and statistical context.
std::size_t rows() const
Returns the number of rows.
Definition Matrix.cpp:601
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