CMP++: Uncertainty Quantification & Bayesian Calibration
Loading...
Searching...
No Matches
kernel++.h
Go to the documentation of this file.
1#ifndef KERNELPP_H
2#define KERNELPP_H
3
4#include "cmp_defines.h"
5
10namespace cmp::kernel {
11
12constexpr double TOL = 1e-12;
13
14
28class Bandwidth {
29 public:
30 virtual ~Bandwidth() = default;
31 virtual Eigen::VectorXd apply(const Eigen::VectorXd& x1, const Eigen::VectorXd& x2) const = 0;
32 virtual double determinant() const = 0;
33 virtual size_t size() const = 0;
34
35 // Gradient methods
36 virtual Eigen::VectorXd gradientOfApply(const Eigen::VectorXd& x1, const Eigen::VectorXd& x2, const size_t &i) const = 0;
37 virtual double gradientOfLogDeterminant(const size_t &i) const = 0;
38
39 // Construct for NLopt routines
40 virtual void setFromVector(const Eigen::VectorXd &params) = 0;
41 virtual Eigen::VectorXd getParams() const = 0;
42
43};
44
57 private:
58 double h_{1.0};
59 size_t dim_{1};
60 public:
62
68 IsotropicBandwidth(const double &h, const size_t &dim) : h_(h), dim_(dim) {};
69
73 Eigen::VectorXd apply(const Eigen::VectorXd& x1, const Eigen::VectorXd& x2) const override;
74
78 double determinant() const override;
79
83 size_t size() const override {
84 return dim_;
85 };
86
90 Eigen::VectorXd gradientOfApply(const Eigen::VectorXd& x1, const Eigen::VectorXd& x2, const size_t &i) const override;
91
95 double gradientOfLogDeterminant(const size_t &i) const override;
96
100 void setFromVector(const Eigen::VectorXd &params) {
101 h_ = params(0);
102 };
103
107 Eigen::VectorXd getParams() const {
108 return Eigen::VectorXd::Constant(1, h_);
109 };
110
114 static std::shared_ptr<Bandwidth> make(const double &h, const size_t &dim) {
115 return std::make_shared<IsotropicBandwidth>(h, dim);
116 };
117
118};
119
132 private:
133 Eigen::VectorXd h_;
134 double det_;
135 public:
137
141 DiagonalBandwidth(const Eigen::VectorXd &h) : h_(h) {
142 det_ = h_.prod();
143 };
144
148 Eigen::VectorXd apply(const Eigen::VectorXd& x1, const Eigen::VectorXd& x2) const override;
149
153 double determinant() const override;
154
155
159 size_t size() const override {
160 return h_.size();
161 };
162
163 // Gradient methods
164 Eigen::VectorXd gradientOfApply(const Eigen::VectorXd& x1, const Eigen::VectorXd& x2, const size_t &i) const override;
165
166 double gradientOfLogDeterminant(const size_t &i) const override;
167
168 void setFromVector(const Eigen::VectorXd &params) override;
169
170 Eigen::VectorXd getParams() const override;
171
172 // Make method
173 static std::shared_ptr<Bandwidth> make(const Eigen::VectorXd &h) {
174 return std::make_shared<DiagonalBandwidth>(h);
175 };
176
177};
178
179// We implement a full bandwidth based on the Cholesky decomposition
197class FullBandwidth : public Bandwidth {
198
199 private:
200 Eigen::LLT<Eigen::MatrixXd> L_;
201 double det_;
202 size_t dim_;
203
204 public:
205 FullBandwidth() = delete;
206
210 FullBandwidth(const Eigen::MatrixXd &LLT) : dim_(LLT.rows()) {
211 if(LLT.rows() != LLT.cols()) {
212 throw std::invalid_argument("Full bandwidth expects a square matrix.");
213 }
214 L_ = Eigen::LLT<Eigen::MatrixXd>(LLT);
215 if(L_.info() != Eigen::Success) {
216 throw std::invalid_argument("The provided matrix is not positive definite.");
217 }
218
219 // Compute determinant as product of diagonal entries of the Cholesky factor
220 // directly to avoid hitting Eigen internals that trigger deprecated enum
221 // bitwise operations.
222 det_ = 1.0;
223 for(size_t i = 0; i < static_cast<size_t>(L_.matrixL().rows()); ++i) {
224 det_ *= L_.matrixL()(i, i);
225 }
226 };
227
231 double determinant() const override;
232
236 size_t size() const {
237 return dim_;
238 };
239
243 std::pair<size_t, size_t> indexToRowCol(const size_t &i) const;
244
248 Eigen::VectorXd apply(const Eigen::VectorXd& x1, const Eigen::VectorXd& x2) const override;
249
253 Eigen::VectorXd gradientOfApply(const Eigen::VectorXd& x1, const Eigen::VectorXd& x2, const size_t &i) const override;
254
258 double gradientOfLogDeterminant(const size_t &i) const override;
259
263 void setFromVector(const Eigen::VectorXd &params) override;
264
268 Eigen::VectorXd getParams() const override;
269
273 static std::shared_ptr<Bandwidth> make(const Eigen::MatrixXd &LLT) {
274 return std::make_shared<FullBandwidth>(LLT);
275 };
276
280 Eigen::MatrixXd matrix() const {
281 return L_.matrixL().toDenseMatrix() * L_.matrixL().transpose().toDenseMatrix();
282
283 };
284
285};
286
287
288
289// Implement Kernels
302class Kernel {
303 public:
304 virtual ~Kernel() = default;
305 virtual double eval(const Eigen::VectorXd& z) const = 0;
306 virtual double normalizationConstant(const size_t &dim) const = 0;
307 virtual double applyToGradient(const Eigen::VectorXd& z, const Eigen::VectorXd& grad_z_i) const = 0;
308
309
310};
311
321class Gaussian : public Kernel {
322 public:
323
324 Gaussian() = default;
325
329 double eval(const Eigen::VectorXd& z_diff) const override;
330
334 double normalizationConstant(const size_t &dim) const override;
335
339 double applyToGradient(const Eigen::VectorXd& z, const Eigen::VectorXd& grad_z_i) const override;
340
344 static std::shared_ptr<Kernel> make() {
345 return std::make_shared<Gaussian>();
346 };
347};
348
358class Epanechnikov : public Kernel {
359 public:
360
361 Epanechnikov() = default;
362
366 double eval(const Eigen::VectorXd& z_diff) const override;
367
371 double normalizationConstant(const size_t &dim) const override;
372
376 double applyToGradient(const Eigen::VectorXd& z, const Eigen::VectorXd& grad_z_i) const override;
377
381 static std::shared_ptr<Kernel> make() {
382 return std::make_shared<Epanechnikov>();
383 };
384};
385
395class Uniform : public Kernel {
396 public:
397
398 Uniform() = default;
399
403 double eval(const Eigen::VectorXd& z_diff) const override;
404
408 double normalizationConstant(const size_t &dim) const override;
409
413 double applyToGradient(const Eigen::VectorXd& z, const Eigen::VectorXd& grad_z_i) const override;
414
418 static std::shared_ptr<Kernel> make() {
419 return std::make_shared<Uniform>();
420 };
421};
422
423
424
425} // namespace cmp::kernel
426
429#endif
Abstract base class for multivariate KDE bandwidth matrices.
Definition kernel++.h:28
virtual Eigen::VectorXd getParams() const =0
virtual ~Bandwidth()=default
virtual Eigen::VectorXd gradientOfApply(const Eigen::VectorXd &x1, const Eigen::VectorXd &x2, const size_t &i) const =0
virtual double determinant() const =0
virtual Eigen::VectorXd apply(const Eigen::VectorXd &x1, const Eigen::VectorXd &x2) const =0
virtual size_t size() const =0
virtual double gradientOfLogDeterminant(const size_t &i) const =0
virtual void setFromVector(const Eigen::VectorXd &params)=0
Diagonal bandwidth matrix (independent parameter per dimension).
Definition kernel++.h:131
void setFromVector(const Eigen::VectorXd &params) override
Definition kernel++.cpp:42
double determinant() const override
Computes the determinant of the diagonal bandwidth matrix.
Definition kernel++.cpp:27
Eigen::VectorXd apply(const Eigen::VectorXd &x1, const Eigen::VectorXd &x2) const override
Scales the coordinate distances independently by 1 / h_d.
Definition kernel++.cpp:23
double gradientOfLogDeterminant(const size_t &i) const override
Definition kernel++.cpp:37
Eigen::VectorXd h_
Diagonal bandwidth parameters vector.
Definition kernel++.h:133
static std::shared_ptr< Bandwidth > make(const Eigen::VectorXd &h)
Definition kernel++.h:173
DiagonalBandwidth(const Eigen::VectorXd &h)
Constructs a DiagonalBandwidth from a parameter vector.
Definition kernel++.h:141
Eigen::VectorXd getParams() const override
Definition kernel++.cpp:53
size_t size() const override
Returns the dimension of the space.
Definition kernel++.h:159
Eigen::VectorXd gradientOfApply(const Eigen::VectorXd &x1, const Eigen::VectorXd &x2, const size_t &i) const override
Definition kernel++.cpp:31
double det_
Precomputed determinant of the diagonal bandwidth matrix.
Definition kernel++.h:134
Epanechnikov (parabolic) density kernel.
Definition kernel++.h:358
double applyToGradient(const Eigen::VectorXd &z, const Eigen::VectorXd &grad_z_i) const override
Computes the gradient of the kernel evaluation.
Definition kernel++.cpp:190
double normalizationConstant(const size_t &dim) const override
Returns the normalization constant for a given dimension.
Definition kernel++.cpp:182
double eval(const Eigen::VectorXd &z_diff) const override
Evaluates the unnormalized Epanechnikov kernel.
Definition kernel++.cpp:174
static std::shared_ptr< Kernel > make()
Factory method for creating an Epanechnikov kernel.
Definition kernel++.h:381
Full covariance bandwidth matrix parameterized by its Cholesky factor.
Definition kernel++.h:197
Eigen::LLT< Eigen::MatrixXd > L_
LDLT/Cholesky factor of the covariance scaling matrix.
Definition kernel++.h:200
size_t size() const
Returns the dimension of the space.
Definition kernel++.h:236
void setFromVector(const Eigen::VectorXd &params) override
Sets the bandwidth parameters from a parameter vector.
Definition kernel++.cpp:114
Eigen::VectorXd gradientOfApply(const Eigen::VectorXd &x1, const Eigen::VectorXd &x2, const size_t &i) const override
Computes the gradient of the scaling transformation with respect to parameter i.
Definition kernel++.cpp:84
double gradientOfLogDeterminant(const size_t &i) const override
Computes the gradient of the log-determinant.
Definition kernel++.cpp:97
Eigen::VectorXd apply(const Eigen::VectorXd &x1, const Eigen::VectorXd &x2) const override
Projects the distance vector using the inverse of the Cholesky factor L.
Definition kernel++.cpp:80
Eigen::VectorXd getParams() const override
Gets the bandwidth parameters as a vector.
Definition kernel++.cpp:145
static std::shared_ptr< Bandwidth > make(const Eigen::MatrixXd &LLT)
Factory method for creating a FullBandwidth.
Definition kernel++.h:273
FullBandwidth(const Eigen::MatrixXd &LLT)
Constructs a FullBandwidth from a positive definite scale matrix.
Definition kernel++.h:210
Eigen::MatrixXd matrix() const
Returns the full density bandwidth matrix.
Definition kernel++.h:280
double det_
Precomputed determinant of the full bandwidth matrix.
Definition kernel++.h:201
double determinant() const override
Computes the determinant of the bandwidth matrix.
Definition kernel++.cpp:59
std::pair< size_t, size_t > indexToRowCol(const size_t &i) const
Maps a flat index to row and column indices of the Cholesky factor.
Definition kernel++.cpp:63
size_t dim_
Dimension of the input space.
Definition kernel++.h:202
Standard Gaussian density kernel.
Definition kernel++.h:321
double applyToGradient(const Eigen::VectorXd &z, const Eigen::VectorXd &grad_z_i) const override
Computes the gradient of the kernel evaluation.
Definition kernel++.cpp:170
static std::shared_ptr< Kernel > make()
Factory method for creating a Gaussian kernel.
Definition kernel++.h:344
double eval(const Eigen::VectorXd &z_diff) const override
Evaluates the unnormalized Gaussian kernel.
Definition kernel++.cpp:161
double normalizationConstant(const size_t &dim) const override
Returns the normalization constant for a given dimension.
Definition kernel++.cpp:166
Isotropic bandwidth matrix (single scalar parameter h).
Definition kernel++.h:56
double h_
Bandwidth scalar parameter.
Definition kernel++.h:58
Eigen::VectorXd gradientOfApply(const Eigen::VectorXd &x1, const Eigen::VectorXd &x2, const size_t &i) const override
Computes the gradient of the scaling transformation with respect to h.
Definition kernel++.cpp:13
double determinant() const override
Computes the determinant of the bandwidth matrix (h^D).
Definition kernel++.cpp:9
void setFromVector(const Eigen::VectorXd &params)
Sets the bandwidth parameter from a parameter vector.
Definition kernel++.h:100
size_t size() const override
Returns the dimension of the space.
Definition kernel++.h:83
Eigen::VectorXd getParams() const
Returns the bandwidth parameter vector.
Definition kernel++.h:107
static std::shared_ptr< Bandwidth > make(const double &h, const size_t &dim)
Factory method for creating an IsotropicBandwidth.
Definition kernel++.h:114
double gradientOfLogDeterminant(const size_t &i) const override
Computes the gradient of the log-determinant (D / h).
Definition kernel++.cpp:17
IsotropicBandwidth(const double &h, const size_t &dim)
Constructs an IsotropicBandwidth object.
Definition kernel++.h:68
size_t dim_
Dimension of the input data.
Definition kernel++.h:59
Eigen::VectorXd apply(const Eigen::VectorXd &x1, const Eigen::VectorXd &x2) const override
Scales the distance between two vectors by 1/h.
Definition kernel++.cpp:5
Abstract base class for KDE density kernel functions.
Definition kernel++.h:302
virtual double normalizationConstant(const size_t &dim) const =0
virtual double eval(const Eigen::VectorXd &z) const =0
virtual ~Kernel()=default
virtual double applyToGradient(const Eigen::VectorXd &z, const Eigen::VectorXd &grad_z_i) const =0
Rectangular (uniform) density kernel.
Definition kernel++.h:395
double normalizationConstant(const size_t &dim) const override
Returns the normalization constant for a given dimension.
Definition kernel++.cpp:209
double applyToGradient(const Eigen::VectorXd &z, const Eigen::VectorXd &grad_z_i) const override
Computes the gradient of the kernel evaluation (always 0 since it is flat).
Definition kernel++.cpp:213
static std::shared_ptr< Kernel > make()
Factory method for creating a Uniform kernel.
Definition kernel++.h:418
double eval(const Eigen::VectorXd &z_diff) const override
Evaluates the unnormalized uniform kernel.
Definition kernel++.cpp:201
Definition kernel++.h:10
constexpr double TOL
Definition kernel++.h:12