contrib/mul/vpdfl/vpdfl_pdf_base.cxx
Go to the documentation of this file.
00001 // This is mul/vpdfl/vpdfl_pdf_base.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author Tim Cootes
00008 // \date 12-Apr-2001
00009 // \brief Base class for Multi-Variate Probability Density Function classes.
00010 
00011 #include "vpdfl_pdf_base.h"
00012 
00013 #include <vcl_cmath.h>
00014 #include <vcl_cassert.h>
00015 #include <vsl/vsl_indent.h>
00016 #include <vsl/vsl_binary_loader.h>
00017 #include <vcl_queue.h>
00018 #include <vpdfl/vpdfl_sampler_base.h>
00019 
00020 //=======================================================================
00021 
00022 vpdfl_pdf_base::vpdfl_pdf_base()
00023 {
00024 }
00025 
00026 //=======================================================================
00027 
00028 vpdfl_pdf_base::~vpdfl_pdf_base()
00029 {
00030 }
00031 
00032 //=======================================================================
00033 
00034 double vpdfl_pdf_base::operator()(const vnl_vector<double>& x) const
00035 {
00036   return vcl_exp(log_p(x));
00037 }
00038 
00039 
00040 double vpdfl_pdf_base::log_prob_thresh(double pass_proportion) const
00041 {
00042   assert(pass_proportion >= 0.0);
00043   assert(pass_proportion < 1.0);
00044 
00045   // The number of samples on the less likely side of the boundary.
00046   // Increase the number for greater reliabililty
00047   const unsigned n_stat = 20;
00048 
00049   double /* above, */ below, lP;
00050   unsigned int nSamples, i;
00051   vnl_vector<double> x;
00052 
00053   vpdfl_sampler_base *sampler = new_sampler();
00054   if (pass_proportion > 0.5)
00055   {
00056     vcl_priority_queue<double, vcl_vector<double>, vcl_less<double> > pq;
00057     //We want at n_stat samples outside the cut-off.
00058     nSamples = (unsigned)(((double)n_stat / (1.0 - pass_proportion)) + 0.5);
00059 
00060     for (i = 0; i < n_stat+1; i++)
00061     {
00062       sampler->sample(x);
00063       pq.push(log_p(x));
00064     }
00065 
00066     for (; i < nSamples; i++)
00067     {
00068       sampler->sample(x);
00069       lP = log_p(x);
00070       // pq.top() should be the greatest value in the queue
00071       if (lP < pq.top())
00072       {
00073         pq.pop();
00074         pq.push(lP);
00075       }
00076     }
00077     // get two values either side of boundary;
00078 #if 0
00079     above = pq.top();
00080 #endif
00081     pq.pop();
00082     below = pq.top();
00083   }
00084   else
00085   {
00086     vcl_priority_queue<double, vcl_vector<double>, vcl_greater<double> > pq;
00087     //We want at n_stat samples inside the cut-off.
00088     nSamples = (unsigned)(((double)n_stat / pass_proportion) + 0.5);
00089 
00090     for (i = 0; i < n_stat+1; i++)
00091     {
00092       sampler->sample(x);
00093       pq.push(log_p(x));
00094     }
00095 
00096     for (; i < nSamples; i++)
00097     {
00098       sampler->sample(x);
00099       lP = log_p(x);
00100       if (lP > pq.top())  // pq.top() should be the smallest value in the queue.
00101       {
00102         pq.pop();
00103         pq.push(lP);
00104       }
00105     }
00106     // get two values either side of boundary;
00107 #if 0
00108     above = pq.top();
00109 #endif
00110     pq.pop();
00111     below = pq.top();
00112   }
00113 
00114   delete sampler;
00115 
00116   // Find geometric mean of probability densities to get boundary (arithmetic mean of logProbs.)
00117 #if 0
00118   return (above + below)/2.0;
00119 #else
00120   return below;
00121 #endif
00122 }
00123 
00124 //: Gradient of log(p(x)) at x
00125 //  Computes gradient df/dx of f(x)=log(p(x)) at x.
00126 //  Default baseclass implementation uses gradient() to compute grad/p
00127 void vpdfl_pdf_base::gradient_logp(vnl_vector<double>& g,
00128                                    const vnl_vector<double>& x) const
00129 {
00130   double p;
00131   gradient(g,x,p);
00132   if (p==0.0)
00133     g.fill(0.0);  // Avoid division by zero.
00134   else
00135     g/=p;
00136 }
00137 
00138 
00139 //=======================================================================
00140 
00141 bool vpdfl_pdf_base::is_valid_pdf() const
00142 {
00143   return mean_.size() == var_.size() && mean_.size() > 0;
00144 }
00145 
00146 
00147 //=======================================================================
00148 
00149 short vpdfl_pdf_base::version_no() const
00150 {
00151   return 1;
00152 }
00153 
00154 //=======================================================================
00155 
00156 void vsl_add_to_binary_loader(const vpdfl_pdf_base& b)
00157 {
00158   vsl_binary_loader<vpdfl_pdf_base>::instance().add(b);
00159 }
00160 
00161 //=======================================================================
00162 
00163 vcl_string vpdfl_pdf_base::is_a() const
00164 {
00165   static vcl_string class_name_ = "vpdfl_pdf_base";
00166   return class_name_;
00167 }
00168 
00169 //=======================================================================
00170 
00171 bool vpdfl_pdf_base::is_class(vcl_string const& s) const
00172 {
00173   return s==vpdfl_pdf_base::is_a();
00174 }
00175 
00176 //=======================================================================
00177 
00178 static void ShowStartVec(vcl_ostream& os, const vnl_vector<double>& v)
00179 {
00180   unsigned int n = 3;
00181   if (n>v.size()) n=v.size();
00182   os<<'(';
00183   for (unsigned int i=0;i<n;++i) os<<v(i)<<' ';
00184   if (v.size()>n) os<<"...";
00185   os<<')';
00186 }
00187 
00188 
00189   // required if data is present in this base class
00190 void vpdfl_pdf_base::print_summary(vcl_ostream& os) const
00191 {
00192   os <<  "N. Dims: "<< mean_.size();
00193   os <<  "  Mean: "; ShowStartVec(os, mean_);
00194   os <<  "  Variance: "; ShowStartVec(os, var_);
00195 }
00196 
00197 //=======================================================================
00198 
00199   // required if data is present in this base class
00200 void vpdfl_pdf_base::b_write(vsl_b_ostream& bfs) const
00201 {
00202   vsl_b_write(bfs, version_no());
00203   vsl_b_write(bfs, mean_);
00204   vsl_b_write(bfs, var_);
00205 }
00206 
00207 //=======================================================================
00208 
00209   // required if data is present in this base class
00210 void vpdfl_pdf_base::b_read(vsl_b_istream& bfs)
00211 {
00212   if (!bfs) return;
00213 
00214   short version;
00215   vsl_b_read(bfs,version);
00216   switch (version)
00217   {
00218     case 1:
00219       vsl_b_read(bfs,mean_);
00220       vsl_b_read(bfs,var_);
00221       break;
00222     default:
00223       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, vpdfl_pdf_base &)\n"
00224                << "           Unknown version number "<< version << '\n';
00225       bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00226       return;
00227   }
00228 }
00229 
00230 
00231 //=======================================================================
00232 
00233 void vsl_b_write(vsl_b_ostream& bfs, const vpdfl_pdf_base& b)
00234 {
00235   b.b_write(bfs);
00236 }
00237 
00238 //=======================================================================
00239 
00240 void vsl_b_read(vsl_b_istream& bfs, vpdfl_pdf_base& b)
00241 {
00242   b.b_read(bfs);
00243 }
00244 
00245 //=======================================================================
00246 
00247 void vsl_print_summary(vcl_ostream& os,const vpdfl_pdf_base& b)
00248 {
00249   os << b.is_a() << ": ";
00250   vsl_indent_inc(os);
00251   b.print_summary(os);
00252   vsl_indent_dec(os);
00253 }
00254 
00255 //=======================================================================
00256 
00257 void vsl_print_summary(vcl_ostream& os,const vpdfl_pdf_base* b)
00258 {
00259   if (b)
00260     vsl_print_summary(os, *b);
00261   else
00262     os << "No vpdfl_pdf_base defined.";
00263 }
00264 
00265 //=======================================================================
00266 
00267 //: Stream output operator for class reference
00268 vcl_ostream& operator<<(vcl_ostream& os,const vpdfl_pdf_base& b)
00269 {
00270   vsl_print_summary(os,b);
00271   return os;
00272 }
00273 
00274 //=======================================================================
00275 
00276 //: Stream output operator for class pointer
00277 vcl_ostream& operator<<(vcl_ostream& os,const vpdfl_pdf_base* b)
00278 {
00279   vsl_print_summary(os,b);
00280   return os;
00281 }
00282