00001 // This is mul/pdf1d/pdf1d_weighted_epanech_kernel_pdf.cxx 00002 00003 //: 00004 // \file 00005 // \brief Univariate Weighted Epanechnikov kernel PDF 00006 // \author Ian Scott 00007 00008 #include "pdf1d_weighted_epanech_kernel_pdf.h" 00009 00010 #include <vcl_cstdlib.h> 00011 #include <vcl_string.h> 00012 #include <vcl_cmath.h> 00013 00014 #include <pdf1d/pdf1d_weighted_epanech_kernel_sampler.h> 00015 #include <pdf1d/pdf1d_sampler.h> 00016 00017 //======================================================================= 00018 00019 pdf1d_weighted_epanech_kernel_pdf::pdf1d_weighted_epanech_kernel_pdf() 00020 { 00021 } 00022 00023 //======================================================================= 00024 //: Define n kernels centred at i*sep (i=0..n-1) 00025 pdf1d_weighted_epanech_kernel_pdf::pdf1d_weighted_epanech_kernel_pdf( 00026 int n, double sep, double width) 00027 { 00028 vnl_vector<double> x(n); 00029 for (int i=0;i<n;++i) x(i)=i*sep; 00030 set_centres(x,width); 00031 weight_.set_size(n); 00032 weight_.fill(1.0); 00033 sum_weights_ = n; 00034 } 00035 00036 //======================================================================= 00037 00038 pdf1d_weighted_epanech_kernel_pdf::~pdf1d_weighted_epanech_kernel_pdf() 00039 { 00040 } 00041 00042 //======================================================================= 00043 00044 pdf1d_sampler* pdf1d_weighted_epanech_kernel_pdf::new_sampler() const 00045 { 00046 pdf1d_weighted_epanech_kernel_sampler *i = new pdf1d_weighted_epanech_kernel_sampler; 00047 i->set_model(*this); 00048 return i; 00049 } 00050 00051 static const double root5 = 2.23606797749978970; //vcl_sqrt(5); 00052 00053 //======================================================================= 00054 //: Probability density at x 00055 double pdf1d_weighted_epanech_kernel_pdf::operator()(double x0) const 00056 { 00057 double p; 00058 const double* x = x_.data_block(); 00059 const double* w = width_.data_block(); 00060 const double* s = weight_.data_block(); 00061 int n = x_.size(); 00062 double k = 0.75/(sum_weights_*root5); 00063 double sum = 0; 00064 00065 for (int i=0;i<n;++i) 00066 { 00067 double dx = (x[i]-x0)/w[i]; 00068 double dx2=dx*dx; 00069 if (dx2<5) sum += s[i]*(1.0-0.2*dx2)/w[i]; 00070 } 00071 00072 p = k*sum; 00073 00074 return p; 00075 } 00076 00077 //======================================================================= 00078 00079 double pdf1d_weighted_epanech_kernel_pdf::log_p(double x) const 00080 { 00081 return vcl_log(pdf1d_weighted_epanech_kernel_pdf::operator()(x)); 00082 } 00083 00084 //======================================================================= 00085 //: Cumulative Probability (P(x'<x) for x' drawn from the distribution) 00086 // CDF of $k(x) = 0.75x(1-x^2/15)/\sqrt{5} + 0.5$ if $x^2<5$ 00087 double pdf1d_weighted_epanech_kernel_pdf::cdf(double x0) const 00088 { 00089 const double* x = x_.data_block(); 00090 const double* w = width_.data_block(); 00091 const double* s = weight_.data_block(); 00092 int n = x_.size(); 00093 double k = 0.75/(root5); 00094 00095 double sum = 0; 00096 for (int i=0;i<n;++i) 00097 { 00098 const double dx = (x0-x[i])/w[i]; 00099 if (dx>=root5) 00100 sum+=s[i]; 00101 else if (dx > -root5) 00102 { 00103 const double dx2 = dx*dx; 00104 sum += s[i]*(k*dx*(1-dx2/15)+0.5); 00105 } 00106 } 00107 00108 return sum/sum_weights_; 00109 } 00110 00111 //: Return true if cdf() uses an analytic implementation 00112 bool pdf1d_weighted_epanech_kernel_pdf::cdf_is_analytic() const 00113 { 00114 return true; 00115 } 00116 00117 //======================================================================= 00118 00119 double pdf1d_weighted_epanech_kernel_pdf::gradient(double x0, 00120 double& p) const 00121 { 00122 const double* x = x_.data_block(); 00123 const double* w = width_.data_block(); 00124 const double* s = weight_.data_block(); 00125 int n = x_.size(); 00126 double sum_p = 0; 00127 double sum_g = 0; 00128 00129 for (int i=0;i<n;++i) 00130 { 00131 double wi = w[i]; 00132 double dx = (x[i]-x0)/wi; 00133 double dx2 = dx*dx; 00134 if (dx2<5) 00135 { 00136 sum_p += s[i] * (1.0-0.2*dx2)/wi; 00137 sum_g += s[i] * dx/wi; 00138 } 00139 } 00140 00141 double k = 1.0/(sum_weights_*root5); 00142 p = sum_p*0.75*k; 00143 00144 return -0.4*k*sum_g; 00145 } 00146 00147 00148 //======================================================================= 00149 00150 double pdf1d_weighted_epanech_kernel_pdf::nearest_plausible(double /*x*/, double /*log_p_min*/) const 00151 { 00152 vcl_cerr<<"pdf1d_weighted_epanech_kernel_pdf::nearest_plausible() not yet implemented.\n"; 00153 vcl_abort(); 00154 return 0.0; 00155 } 00156 00157 //======================================================================= 00158 00159 vcl_string pdf1d_weighted_epanech_kernel_pdf::is_a() const 00160 { 00161 static vcl_string class_name_ = "pdf1d_weighted_epanech_kernel_pdf"; 00162 return class_name_; 00163 } 00164 00165 //======================================================================= 00166 00167 bool pdf1d_weighted_epanech_kernel_pdf::is_class(vcl_string const& s) const 00168 { 00169 return pdf1d_weighted_kernel_pdf::is_class(s) || s==pdf1d_weighted_epanech_kernel_pdf::is_a(); 00170 } 00171 00172 //======================================================================= 00173 00174 short pdf1d_weighted_epanech_kernel_pdf::version_no() const 00175 { 00176 return 1; 00177 } 00178 00179 //======================================================================= 00180 00181 pdf1d_pdf* pdf1d_weighted_epanech_kernel_pdf::clone() const 00182 { 00183 return new pdf1d_weighted_epanech_kernel_pdf(*this); 00184 }