contrib/mul/pdf1d/pdf1d_bhat_overlap.cxx
Go to the documentation of this file.
00001 // This is mul/pdf1d/pdf1d_bhat_overlap.cxx
00002 #include "pdf1d_bhat_overlap.h"
00003 //:
00004 // \file
00005 // \author Tim Cootes
00006 // \brief Functions to calculate Bhattacharyya overlap.
00007 
00008 #include <pdf1d/pdf1d_sampler.h>
00009 #include <vcl_cmath.h>
00010 #include <vnl/vnl_vector.h>
00011 #include <vnl/vnl_math.h>
00012 
00013 //: Estimate Bhattacharyya overlap between two pdfs
00014 //  If use_analytic is true and an analytic form exists, it will be used.
00015 //  Otherwise n_samples are drawn from pdf1 and used to estimate the overlap
00016 double pdf1d_bhat_overlap(const pdf1d_pdf& pdf1, const pdf1d_pdf& pdf2,
00017                           int n_samples, bool use_analytic)
00018 {
00019   if (use_analytic)
00020   {
00021     // Check for known analytic cases
00022     if (pdf1.is_class("pdf1d_gaussian") && pdf2.is_class("pdf1d_gaussian"))
00023       return pdf1d_bhat_overlap_gaussians(pdf1,pdf2);
00024   }
00025 
00026   // Otherwise sample from pdf1 and use this to estimate the overlap
00027 
00028   vnl_vector<double> x(n_samples),p(n_samples);
00029 
00030   pdf1d_sampler* sampler = pdf1.new_sampler();
00031   sampler->regular_samples_and_prob(x,p);
00032   delete sampler;
00033 
00034   return pdf1d_bhat_overlap(pdf2,x.data_block(),p.data_block(),n_samples);
00035 }
00036 
00037 // Bhat. overlap between a pdf and a sampled distribution.
00038 // Second distribution is known to have pdf of p[i] when evaluated at x[i]
00039 // x[i] must be representative samples from the pdf (i.e. randomly sampled
00040 // from it, or selected so as to be equally spread in cum.prob. space).
00041 double pdf1d_bhat_overlap(const pdf1d_pdf& pdf,
00042                           const double* x,
00043                           const double* p, int n)
00044 {
00045   // Use more efficient calculation for Gaussian case
00046   if (pdf.is_class("pdf1d_gaussian"))
00047     return pdf1d_bhat_overlap_gaussian(pdf.mean(),pdf.variance(),x,p,n);
00048 
00049   // Otherwise use a general form
00050   double sum = 0;
00051   for (int i=0;i<n;++i)
00052   {
00053     sum += vcl_sqrt( pdf(x[i])/p[i] );
00054   }
00055 
00056   return sum/n;
00057 }
00058 
00059 // Bhat. overlap between 1D Gaussian and sampled distribution.
00060 double pdf1d_bhat_overlap_gaussian(double m, double v,
00061                                    const double* x,
00062                                    const double* p, int n)
00063 {
00064   double k = vnl_math::one_over_sqrt2pi/vcl_sqrt(v);
00065 
00066   double sum = 0;
00067   for (int i=0;i<n;++i)
00068   {
00069     double dx=x[i]-m;
00070     double pgi = k*vcl_exp(-0.5*dx*dx/v);
00071     sum += vcl_sqrt(pgi/p[i]);
00072   }
00073   return sum/n;
00074 }
00075 
00076 //: Bhat. overlap between two 1D Gaussians
00077 double pdf1d_bhat_overlap_gaussians(double m1, double v1,
00078                                     double m2, double v2)
00079 {
00080   double dm = m1-m2;
00081   double k = vcl_sqrt(2*vcl_sqrt(v1*v2))/vcl_sqrt(v1+v2);
00082   return k * vcl_exp(-0.25*dm*dm/(v1+v2));
00083 }
00084 
00085 //: Bhat. overlap between two 1D Gaussians
00086 double pdf1d_bhat_overlap_gaussians(const pdf1d_pdf& g1, const pdf1d_pdf& g2)
00087 {
00088   return pdf1d_bhat_overlap_gaussians(g1.mean(),g1.variance(),g2.mean(),g2.variance());
00089 }
00090 
00091 //: Bhat. overlap between Gaussian and arbitrary pdf (estimate by sampling at n points)
00092 double pdf1d_bhat_overlap_gaussian_with_pdf(double m, double v, const pdf1d_pdf& pdf, int n)
00093 {
00094   if (pdf.is_class("pdf1d_gaussian"))
00095     return pdf1d_bhat_overlap_gaussians(m,v,pdf.mean(),pdf.variance());
00096 
00097   double k = vnl_math::one_over_sqrt2pi/vcl_sqrt(v);
00098   double sd = vcl_sqrt(v);
00099 
00100   // Place n samples along range [-3,3]*sd
00101   double dx = 6.0/(n-1);
00102   double x = -0.5*dx*(n-1);
00103   double sum = 0.0;
00104   for (int i=0;i<n;++i)
00105   {
00106     double pgi = k*vcl_exp(-0.5*x*x);
00107     sum += vcl_sqrt(pgi*pdf(m+sd*x));
00108     x += dx;
00109   }
00110 
00111   // Width of each bin = sd*dx in original space
00112 
00113   return sum*dx*sd;
00114 }
00115 
00116 //: Bhat. overlap between Gaussian and arbitrary pdf (estimate by sampling at n points)
00117 double pdf1d_bhat_overlap_gaussian_with_pdf(const pdf1d_pdf& g, const pdf1d_pdf& pdf, int n)
00118 {
00119   return pdf1d_bhat_overlap_gaussian_with_pdf(g.mean(),g.variance(),pdf,n);
00120 }
00121