contrib/mul/pdf1d/pdf1d_epanech_kernel_pdf.cxx
Go to the documentation of this file.
00001 // This is mul/pdf1d/pdf1d_epanech_kernel_pdf.cxx
00002 
00003 //:
00004 // \file
00005 // \brief Univariate Epanechnikov kernel PDF
00006 // \author Tim Cootes
00007 
00008 #include "pdf1d_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_epanech_kernel_pdf_sampler.h>
00015 #include <pdf1d/pdf1d_sampler.h>
00016 
00017 //=======================================================================
00018 
00019 pdf1d_epanech_kernel_pdf::pdf1d_epanech_kernel_pdf()
00020 {
00021 }
00022 
00023 //: Define n kernels centred at i*sep (i=0..n-1)
00024 pdf1d_epanech_kernel_pdf::pdf1d_epanech_kernel_pdf(
00025                             int n, double sep, double width)
00026 {
00027   vnl_vector<double> x(n);
00028   for (int i=0;i<n;++i) x[i]=i*sep;
00029   set_centres(x,width);
00030 }
00031 
00032 //=======================================================================
00033 
00034 pdf1d_epanech_kernel_pdf::~pdf1d_epanech_kernel_pdf()
00035 {
00036 }
00037 
00038 //=======================================================================
00039 
00040 
00041 pdf1d_sampler* pdf1d_epanech_kernel_pdf::new_sampler() const
00042 {
00043   pdf1d_epanech_kernel_pdf_sampler *i = new pdf1d_epanech_kernel_pdf_sampler;
00044   i->set_model(*this);
00045   return i;
00046 }
00047 
00048 static const double root5 = 2.23606797749978970; //vcl_sqrt(5);
00049 
00050 //=======================================================================
00051 //: Probability density at x
00052 double pdf1d_epanech_kernel_pdf::operator()(double x0) const
00053 {
00054   double p;
00055   const double* x = x_.data_block();
00056   const double* w = width_.data_block();
00057   int n = x_.size();
00058   double k = 0.75/(n*root5);
00059   double sum = 0;
00060 
00061   for (int i=0;i<n;++i)
00062   {
00063     double dx = (x[i]-x0)/w[i];
00064     double dx2=dx*dx;
00065     if (dx2<5) sum += (1.0-0.2*dx2)/w[i];
00066   }
00067 
00068   p = k*sum;
00069 
00070   return p;
00071 }
00072 
00073   // Probability densities:
00074 double pdf1d_epanech_kernel_pdf::log_p(double x) const
00075 {
00076   return vcl_log(pdf1d_epanech_kernel_pdf::operator()(x));
00077 }
00078 
00079 //: Cumulative Probability (P(x'<x) for x' drawn from the distribution)
00080 // CDF of $k(x) = 0.75x(1-x^2/15)/\sqrt{5} + 0.5$ if $x^2<5$
00081 double pdf1d_epanech_kernel_pdf::cdf(double x0) const
00082 {
00083   const double* x = x_.data_block();
00084   const double* w = width_.data_block();
00085   int n = x_.size();
00086   double k = 0.75/(root5);
00087 
00088   double sum = 0;
00089   for (int i=0;i<n;++i)
00090   {
00091     double dx = (x0-x[i])/w[i];
00092     if (dx>=root5) sum+=1;
00093     else if (dx > -root5)
00094     {
00095       const double dx2 = dx*dx;
00096       sum += (k*dx*(1-dx2/15)+0.5);
00097     }
00098   }
00099 
00100   return sum/n;
00101 }
00102 
00103 //: Return true if cdf() uses an analytic implementation
00104 bool pdf1d_epanech_kernel_pdf::cdf_is_analytic() const
00105 {
00106   return true;
00107 }
00108 
00109 //=======================================================================
00110 
00111 
00112 double pdf1d_epanech_kernel_pdf::gradient(double x0,
00113                                           double& p) const
00114 {
00115   const double* x = x_.data_block();
00116   const double* w = width_.data_block();
00117   int n = x_.size();
00118   double sum_p = 0;
00119   double sum_g = 0;
00120 
00121   for (int i=0;i<n;++i)
00122   {
00123     double wi = w[i];
00124     double dx = (x[i]-x0)/wi;
00125     double dx2 = dx*dx;
00126     if (dx2<5)
00127     {
00128       sum_p += (1.0-0.2*dx2)/wi;
00129       sum_g += dx/wi;
00130     }
00131   }
00132 
00133   double k = 1.0/(n*root5);
00134   p = sum_p*0.75*k;
00135 
00136   return -0.4*k*sum_g;
00137 }
00138 
00139 //=======================================================================
00140 
00141 double pdf1d_epanech_kernel_pdf::nearest_plausible(double /*x*/, double /*log_p_min*/) const
00142 {
00143   vcl_cerr<<"pdf1d_epanech_kernel_pdf::nearest_plausible() not yet implemented.\n";
00144   vcl_abort();
00145   return 0.0;
00146 }
00147 
00148 //=======================================================================
00149 // Method: is_a
00150 //=======================================================================
00151 
00152 vcl_string pdf1d_epanech_kernel_pdf::is_a() const
00153 {
00154   static vcl_string class_name_ = "pdf1d_epanech_kernel_pdf";
00155   return class_name_;
00156 }
00157 
00158 //=======================================================================
00159 // Method: is_class
00160 //=======================================================================
00161 
00162 bool pdf1d_epanech_kernel_pdf::is_class(vcl_string const& s) const
00163 {
00164   return pdf1d_kernel_pdf::is_class(s) || s==pdf1d_epanech_kernel_pdf::is_a();
00165 }
00166 
00167 //=======================================================================
00168 // Method: version_no
00169 //=======================================================================
00170 
00171 short pdf1d_epanech_kernel_pdf::version_no() const
00172 {
00173   return 1;
00174 }
00175 
00176 //=======================================================================
00177 // Method: clone
00178 //=======================================================================
00179 
00180 pdf1d_pdf* pdf1d_epanech_kernel_pdf::clone() const
00181 {
00182   return new pdf1d_epanech_kernel_pdf(*this);
00183 }
00184 
00185 //=======================================================================
00186 // Method: print
00187 //=======================================================================
00188 
00189 
00190 void pdf1d_epanech_kernel_pdf::print_summary(vcl_ostream& os) const
00191 {
00192   pdf1d_pdf::print_summary(os);
00193   os << '\n';
00194 }
00195 
00196 //=======================================================================
00197 // Method: save
00198 //=======================================================================
00199 
00200 void pdf1d_epanech_kernel_pdf::b_write(vsl_b_ostream& bfs) const
00201 {
00202   vsl_b_write(bfs,is_a());
00203   vsl_b_write(bfs,version_no());
00204   pdf1d_kernel_pdf::b_write(bfs);
00205 }
00206 
00207 //=======================================================================
00208 // Method: load
00209 //=======================================================================
00210 
00211 void pdf1d_epanech_kernel_pdf::b_read(vsl_b_istream& bfs)
00212 {
00213   if (!bfs) return;
00214 
00215   vcl_string name;
00216   vsl_b_read(bfs,name);
00217   if (name != is_a())
00218   {
00219     vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_epanech_kernel_pdf &)\n"
00220              << "           Attempted to load object of type "
00221              << name <<" into object of type " << is_a() << vcl_endl;
00222     bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00223     return;
00224   }
00225 
00226   short version;
00227   vsl_b_read(bfs,version);
00228   switch (version)
00229   {
00230     case (1):
00231       pdf1d_kernel_pdf::b_read(bfs);
00232       break;
00233     default:
00234       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_epanech_kernel_pdf &)\n"
00235                << "           Unknown version number "<< version << vcl_endl;
00236       bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00237       return;
00238   }
00239 }
00240 
00241 //==================< end of pdf1d_epanech_kernel_pdf_pdf.cxx >====================