pointprocesses/estimators/
kernels.rs

1//! Kernel structs.
2
3/// Trait for non-parametric regression kernels of the form
4/// $$
5///     K_h(x, x') = D\left(\frac{|x-x'|}{h}\right)
6/// $$
7pub trait RegKernel {
8    fn eval(&self, x: f64, xi: f64) -> f64;
9}
10
11/// Trait for kernel mass integrals.
12pub trait RegKernelMass: RegKernel {
13    /// Compute the mass of the kernel between `a` and `b` shifted by `x`
14    /// $$
15    ///     \int_a^b K_h(x - u)\\, du
16    /// $$
17    fn eval_mass(&self, x: f64, a: f64, b: f64) -> f64;
18}
19
20/// Homogeneous fixed-bandwidth Gaussian kernel,
21/// of the form
22/// $$
23///     K_h(x, x') = \exp\left(
24///     -\frac{(x-x')^2}{2h^2}
25///     \right)
26/// $$
27#[derive(Debug,Clone,Copy)]
28pub struct GaussianKernel {
29    bandwidth: f64
30}
31
32impl GaussianKernel {
33    pub fn new(bandwidth: f64) -> Self {
34        GaussianKernel { bandwidth }
35    }
36}
37
38impl RegKernel for GaussianKernel {
39    fn eval(&self, x: f64, xi: f64) -> f64 {
40        let z = (x - xi) / self.bandwidth;
41        (-z * z / 2.).exp()
42    }
43}
44
45/// Fixed-bandwidth nearest-neighbor (or uniform) kernel,
46/// $$
47///     K_h(x, x') = \mathbf{1}_{|x - x'| < h}
48/// $$
49pub struct NearestNeighborKernel {
50    bandwidth: f64
51}
52
53impl NearestNeighborKernel {
54    pub fn new(bandwidth: f64) -> Self {
55        Self { bandwidth }
56    }
57}
58
59impl RegKernel for NearestNeighborKernel {
60    fn eval(&self, x: f64, xi: f64) -> f64 {
61        if (x - xi).abs() < self.bandwidth {
62            1.0
63        } else {
64            0.0
65        }
66    }
67}
68
69impl RegKernelMass for NearestNeighborKernel {
70    fn eval_mass(&self, x: f64, a: f64, b: f64) -> f64 {
71        let h = self.bandwidth;
72        let up = b.min(x + h);
73        let dw = a.max(x - h);
74        up - dw
75    }
76}
77
78/// The Epanechnikov kernel is given by
79/// $$
80///     K_h(x, x') = D\left(
81///     \frac{|x-x'|}{h}
82///     \right)
83/// $$
84/// where $D(u) = \frac34(1-u^2)\mathbf{1}_{|u|\leq 1}$.
85#[derive(Debug,Clone,Copy)]
86pub struct EpanechnikovKernel {
87    bandwidth: f64
88}
89
90impl EpanechnikovKernel {
91    /// Instantiate a new Epanechnikov kernel.
92    pub fn new(bandwidth: f64) -> Self {
93        Self { bandwidth }
94    }
95}
96
97impl RegKernel for EpanechnikovKernel {
98    fn eval(&self, x: f64, xi: f64) -> f64 {
99        if x.abs() > 1. {
100            0.
101        }
102        else {
103            let dx = (x - xi) / self.bandwidth;
104            0.75 * (1.0 - dx * dx)
105        }
106    }
107}