core/vpdl/vpdl_kernel_gaussian_sfbw.h
Go to the documentation of this file.
00001 // This is core/vpdl/vpdl_kernel_gaussian_sfbw.h
00002 #ifndef vpdl_kernel_gaussian_sfbw_h_
00003 #define vpdl_kernel_gaussian_sfbw_h_
00004 //:
00005 // \file
00006 // \author Matthew Leotta
00007 // \date February 24, 2009
00008 // \brief A fixed bandwidth spherical Gaussian kernel distribution
00009 //
00010 // \verbatim
00011 //  Modifications
00012 //   None
00013 // \endverbatim
00014 
00015 #include <vpdl/vpdl_kernel_base.h>
00016 #include <vpdl/vpdt/vpdt_access.h>
00017 #include <vnl/vnl_erf.h>
00018 #include <vcl_limits.h>
00019 #include <vcl_cassert.h>
00020 
00021 //: A fixed bandwidth spherical Gaussian kernel distribution
00022 // The bandwidth is the standard deviation of the Gaussian kernel.
00023 template<class T, unsigned int n=0>
00024 class vpdl_kernel_gaussian_sfbw : public vpdl_kernel_fbw_base<T,n>
00025 {
00026  public:
00027   //: the data type used for vectors
00028   typedef typename vpdt_field_default<T,n>::type vector;
00029   //: the data type used for matrices
00030   typedef typename vpdt_field_traits<vector>::matrix_type matrix;
00031 
00032   //: Default Constructor
00033   vpdl_kernel_gaussian_sfbw() {}
00034 
00035   //: Constructor - from sample centers and bandwidth (variance)
00036   vpdl_kernel_gaussian_sfbw(const vcl_vector<vector>& samplez,
00037                             T bandwid = T(1))
00038   : vpdl_kernel_fbw_base<T,n>(samplez,bandwid) {}
00039 
00040   //: Create a copy on the heap and return base class pointer
00041   virtual vpdl_distribution<T,n>* clone() const
00042   {
00043     return new vpdl_kernel_gaussian_sfbw<T,n>(*this);
00044   }
00045 
00046   //: Evaluate the unnormalized density at a point
00047   virtual T density(const vector& pt) const
00048   {
00049     const unsigned int nc = this->num_components();
00050     if (nc <= 0)
00051       return 0.0;
00052 
00053     const unsigned int d = this->dimension();
00054     T sum = T(0);
00055     typedef typename vcl_vector<vector>::const_iterator vitr;
00056     for (vitr s=this->samples().begin(); s!=this->samples().end(); ++s) {
00057       T ssd = T(0);
00058       for (unsigned int i=0; i<d; ++i) {
00059         T tmp = (vpdt_index(pt,i)-vpdt_index(*s,i))/this->bandwidth();
00060         ssd += tmp*tmp;
00061       }
00062       sum += T(vcl_exp(-0.5*ssd));
00063     }
00064 
00065     return sum;
00066   }
00067 
00068   //: Evaluate the probability density at a point
00069   virtual T prob_density(const vector& pt) const
00070   {
00071     const unsigned int nc = this->num_components();
00072     if (nc <= 0)
00073       return 0.0;
00074 
00075     return density(pt)*this->norm_const();
00076   }
00077 
00078   //: Compute the gradient of the unnormalized density at a point
00079   // \return the density at \a pt since it is usually needed as well, and
00080   //         is often trivial to compute while computing gradient
00081   // \retval g the gradient vector
00082   virtual T gradient_density(const vector& pt, vector& g) const
00083   {
00084     const unsigned int d = this->dimension();
00085     vpdt_set_size(g,d);
00086     vpdt_fill(g,T(0));
00087     const unsigned int nc = this->num_components();
00088     if (nc <= 0)
00089       return 0.0;
00090 
00091     T sum = T(0);
00092     vector g_s;
00093     vpdt_set_size(g_s,d);
00094     typedef typename vcl_vector<vector>::const_iterator vitr;
00095     for (vitr s=this->samples().begin(); s!=this->samples().end(); ++s) {
00096       T ssd = T(0);
00097       for (unsigned int i=0; i<d; ++i) {
00098         T tmp = (vpdt_index(pt,i)-vpdt_index(*s,i))/this->bandwidth();
00099         vpdt_index(g_s,i) = tmp/this->bandwidth();
00100         ssd += tmp*tmp;
00101       }
00102       T dens = T(vcl_exp(-0.5*ssd));
00103       g_s *= -dens;
00104       sum += dens;
00105       g += g_s;
00106     }
00107 
00108     return sum;
00109   }
00110 
00111   //: Evaluate the cumulative distribution function at a point
00112   // This is the integral of the density function from negative infinity
00113   // (in all dimensions) to the point in question
00114   virtual T cumulative_prob(const vector& pt) const
00115   {
00116     const unsigned int nc = this->num_components();
00117     if (nc <= 0)
00118       return 0.0;
00119 
00120     const unsigned int d = this->dimension();
00121     double s2 = 1/(this->bandwidth()*vcl_sqrt(2.0));
00122 
00123     double sum = 0.0;
00124     typedef typename vcl_vector<vector>::const_iterator vitr;
00125     for (vitr s=this->samples().begin(); s!=this->samples().end(); ++s) {
00126       double val = 1.0;
00127       for (unsigned int i=0; i<d; ++i) {
00128         val *= 0.5*vnl_erf(s2*(vpdt_index(pt,i)-vpdt_index(*s,i))) + 0.5;
00129       }
00130       sum += val;
00131     }
00132     return static_cast<T>(sum/nc);
00133   }
00134 
00135   //: The probability of being in an axis-aligned box
00136   // The box is defined by two points, the minimum and maximum.
00137   // Reimplemented for efficiency since the axis are independent
00138   T box_prob(const vector& min_pt, const vector& max_pt) const
00139   {
00140     const unsigned int nc = this->num_components();
00141     if (nc <= 0)
00142       return 0.0;
00143 
00144     const unsigned int dim = this->dimension();
00145     double s2 = 1/(this->bandwidth()*vcl_sqrt(2.0));
00146 
00147     double sum = 0.0;
00148     typedef typename vcl_vector<vector>::const_iterator vitr;
00149     for (vitr s=this->samples().begin(); s!=this->samples().end(); ++s) {
00150       double prob = 1.0;
00151       for (unsigned int i=0; i<dim; ++i) {
00152         if (vpdt_index(max_pt,i)<=vpdt_index(min_pt,i))
00153           return T(0);
00154         prob *= (vnl_erf(s2*(vpdt_index(max_pt,i)-vpdt_index(*s,i))) -
00155                  vnl_erf(s2*(vpdt_index(min_pt,i)-vpdt_index(*s,i))))/2;
00156       }
00157       sum += prob;
00158     }
00159     return static_cast<T>(sum/nc);
00160   }
00161 
00162   //: Compute the covariance of the distribution.
00163   virtual void compute_covar(matrix& covar) const
00164   {
00165     const unsigned int d = this->dimension();
00166     const unsigned int nc = this->num_components();
00167     vector mean;
00168     vpdt_set_size(covar,d);
00169     vpdt_fill(covar,T(0));
00170     vpdt_set_size(mean,d);
00171     vpdt_fill(mean,T(0));
00172     typedef typename vcl_vector<vector>::const_iterator samp_itr;
00173     for (samp_itr s = this->samples().begin(); s != this->samples().end(); ++s) {
00174       covar += outer_product(*s,*s);
00175       mean += *s;
00176     }
00177     mean /= T(nc);
00178     covar /= T(nc);
00179     covar -= outer_product(mean,mean);
00180     T var = this->bandwidth()*this->bandwidth();
00181     for (unsigned int i=0; i<d; ++i)
00182       vpdt_index(covar,i,i) += var;
00183   }
00184 
00185   //: The normalization constant for the kernel
00186   virtual T kernel_norm_const() const
00187   {
00188     const unsigned int dim = this->dimension();
00189     double v2pi = this->bandwidth()*this->bandwidth()*2.0*vnl_math::pi;
00190     double denom = v2pi;
00191     for (unsigned int i=1; i<dim; ++i)
00192       denom *= v2pi;
00193 
00194     return static_cast<T>(vcl_sqrt(1/denom));
00195   }
00196 };
00197 
00198 
00199 #endif // vpdl_kernel_gaussian_sfbw_h_