contrib/mul/pdf1d/pdf1d_weighted_epanech_kernel_pdf.cxx
Go to the documentation of this file.
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 }