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