contrib/brl/bbas/bsta/bsta_sampler.txx
Go to the documentation of this file.
00001 // This is brl/bbas/bsta/bsta_sampler.txx
00002 #ifndef bsta_sampler_txx_
00003 #define bsta_sampler_txx_
00004 //:
00005 // \file
00006 
00007 #include "bsta_sampler.h"
00008 #include <vnl/vnl_random.h>
00009 #include <vcl_cstdlib.h>
00010 #include <vcl_set.h>
00011 #include <vcl_utility.h>
00012 #include <vcl_algorithm.h>
00013 
00014 //: For sorting pairs by their first element
00015 
00016 template<class T>
00017 class first_less
00018 {
00019  public:
00020   bool
00021   operator()( const vcl_pair<float,T>& left_pair,
00022               const vcl_pair<float,T>& right_pair ) const
00023   {
00024     return left_pair.first < right_pair.first;
00025   }
00026 };
00027 
00028 //: wrapper around version with user-provided random generator
00029 template <class T>
00030 bool bsta_sampler<T>::sample(vcl_vector<T>& samples, vcl_vector<float>& p,
00031                              unsigned cnt, vcl_vector<T>& out)
00032 {
00033   vnl_random rand;
00034   return sample(samples,p,cnt,out,rand);
00035 }
00036 
00037 
00038 //: put cnt samples into output vector wrt given probabilities
00039 //  The sum of probabilities should sum to (approx.) 1; otherwise return false
00040 template <class T>
00041 bool bsta_sampler<T>::sample(vcl_vector<T>& samples, vcl_vector<float>& p,
00042                              unsigned cnt, vcl_vector<T>& out, vnl_random &rng) {
00043   if (p.size() != samples.size())
00044     return false;
00045   if (!p.size())
00046     return false;
00047 
00048   vcl_set<vcl_pair<float, unsigned>, first_less<unsigned> > accum_p;
00049   accum_p.insert(vcl_pair<float, unsigned>(p[0], 0));  // put the id of the sample
00050 
00051   for (unsigned i = 1; i < p.size(); i++) {
00052     float accum = (*(accum_p.rbegin())).first + p[i];
00053     accum_p.insert(vcl_pair<float, unsigned>(accum, i));
00054   }
00055   float last_val = (*(accum_p.rbegin())).first;
00056   unsigned last_id = (*(accum_p.rbegin())).second;
00057   if (last_val > 1.015625f || last_val < 0.984375f)
00058     return false;
00059 
00060   for (unsigned i = 0; i < cnt; i++) {
00061     float r = (float)(rng.drand32());
00062     if (r >= last_val) {
00063       out.push_back(samples[last_id]);
00064     } else {
00065       vcl_pair<float, unsigned> search_key(r, 0);
00066       unsigned r_id = (*(accum_p.upper_bound(search_key))).second;
00067       out.push_back(samples[r_id]);
00068     }
00069   }
00070 
00071   return true;
00072 }
00073 
00074 //: sample from a joint histogram treating it as a discrete prob distribution
00075 template <class T>
00076 bool bsta_sampler<T>::sample(const bsta_joint_histogram<float>& jh, unsigned cnt, vcl_vector<vcl_pair<float, float> >& out)
00077 {
00078   vnl_random rng;
00079   return sample(jh, cnt, out, rng);
00080 }
00081 
00082 //: sample from a joint histogram treating it as a discrete prob distribution
00083 // User provided vnl_random
00084 template <class T>
00085 bool bsta_sampler<T>::sample(const bsta_joint_histogram<float>& jh, unsigned cnt, vcl_vector<vcl_pair<float, float> >& out, vnl_random &rng)
00086 {
00087   unsigned int na = jh.nbins_a();
00088   unsigned int nb = jh.nbins_b();
00089 
00090   vcl_set<vcl_pair<float, vcl_pair<unsigned, unsigned> >, first_less<vcl_pair<unsigned, unsigned> > > accum_p;
00091   vcl_pair<unsigned, unsigned> pi(0,0);
00092   float p_0 = jh.p((unsigned)0,(unsigned)0);
00093   accum_p.insert(vcl_pair<float, vcl_pair<unsigned, unsigned> >(p_0, pi));  // put the id of the sample
00094 
00095   // first scan the first row
00096   for (unsigned ib = 1; ib < nb; ib++) {
00097     vcl_pair<unsigned, unsigned> pi(0,ib);
00098 
00099     float accum = (*(accum_p.rbegin())).first + jh.p(0, ib);
00100     accum_p.insert(vcl_pair<float, vcl_pair<unsigned, unsigned> >(accum, pi));
00101   }
00102 
00103   // now do the rest of the rows
00104   for (unsigned ia = 1; ia < na; ia++)
00105     for (unsigned ib = 0; ib < nb; ib++) {
00106       vcl_pair<unsigned, unsigned> pi(ia,ib);
00107 
00108       float accum = (*(accum_p.rbegin())).first + jh.p(ia, ib);
00109       accum_p.insert(vcl_pair<float, vcl_pair<unsigned, unsigned> >(accum, pi));
00110     }
00111 
00112   float last_val = (*(accum_p.rbegin())).first;
00113   //unsigned last_id = (*(accum_p.rbegin())).second;
00114 
00115   if (last_val > 1.015625f || last_val < 0.984375f)
00116     return false;
00117 
00118   for (unsigned i = 0; i < cnt; i++) {
00119     float r = (float)(rng.drand32());
00120     if (r >= last_val) {
00121       // push the last sample in the histogram
00122       vcl_pair<float, float> out_sample(jh.min_a() + na*jh.delta_a(), jh.min_b() + nb*jh.delta_b());
00123       out.push_back(out_sample);
00124     } else {
00125       vcl_pair<float, vcl_pair<unsigned, unsigned> > search_key(r, vcl_pair<unsigned, unsigned>(0, 0));
00126       vcl_pair<unsigned, unsigned> r_id = (*(accum_p.upper_bound(search_key))).second;
00127       vcl_pair<float, float> out_sample(jh.min_a() + (r_id.first+1)*jh.delta_a(), jh.min_b() + (r_id.second+1)*jh.delta_b());
00128       out.push_back(out_sample);
00129     }
00130   }
00131 
00132   return true;
00133 }
00134 
00135 bool first_greater(const vcl_pair<float,vcl_pair<unsigned, unsigned> >& left_pair,
00136                    const vcl_pair<float,vcl_pair<unsigned, unsigned> >& right_pair )
00137 {
00138   return left_pair.first > right_pair.first;
00139 }
00140 
00141 
00142 //: sample in the decreasing order of likelihood (i.e. the most likely bin will be returned as the first sample)
00143 template <class T>
00144 bool bsta_sampler<T>::sample_in_likelihood_order(const bsta_joint_histogram<float>& jh, unsigned cnt, vcl_vector<vcl_pair<float, float> >& out)
00145 {
00146   unsigned int na = jh.nbins_a();
00147   unsigned int nb = jh.nbins_b();
00148 
00149   vcl_vector<vcl_pair<float, vcl_pair<unsigned, unsigned> > > arr;
00150   for (unsigned ia = 0; ia < na; ia++) {
00151     for (unsigned ib = 0; ib < nb; ib++) {
00152       vcl_pair<unsigned, unsigned> ind(ia, ib);
00153       vcl_pair<float, vcl_pair<unsigned, unsigned> > val(jh.p(ia, ib), ind);
00154       arr.push_back(val);
00155     }
00156   }
00157 
00158   vcl_sort(arr.begin(), arr.end(), first_greater);
00159   unsigned size = arr.size() < cnt ? arr.size() : cnt;
00160   for (unsigned i = 0; i < size; i++) {
00161     //vcl_cout << "sampled from bina: " << arr[i].second.first << " binb: " << arr[i].second.second << "!\n";
00162     vcl_pair<float, float> out_p(jh.min_a() + (arr[i].second.first+1)*jh.delta_a(), jh.min_b() + (arr[i].second.second+1)*jh.delta_b());
00163     out.push_back(out_p);
00164   }
00165 
00166   return true;
00167 }
00168 
00169 //: sample in the decreasing order of likelihood (i.e. the most likely bin will be returned as the first sample)
00170 template <class T>
00171 bool bsta_sampler<T>::sample_in_likelihood_order(const bsta_joint_histogram<float>& jh, unsigned cnt, vcl_vector<vcl_pair<unsigned, unsigned> >& out_indices)
00172 {
00173   unsigned int na = jh.nbins_a();
00174   unsigned int nb = jh.nbins_b();
00175 
00176   vcl_vector<vcl_pair<float, vcl_pair<unsigned, unsigned> > > arr;
00177   for (unsigned ia = 0; ia < na; ia++) {
00178     for (unsigned ib = 0; ib < nb; ib++) {
00179       vcl_pair<unsigned, unsigned> ind(ia, ib);
00180       vcl_pair<float, vcl_pair<unsigned, unsigned> > val(jh.p(ia, ib), ind);
00181       arr.push_back(val);
00182     }
00183   }
00184 
00185   vcl_sort(arr.begin(), arr.end(), first_greater);
00186   unsigned size = arr.size() < cnt ? arr.size() : cnt;
00187   for (unsigned i = 0; i < size; i++) {
00188     //vcl_cout << "sampled from bina: " << arr[i].second.first << " binb: " << arr[i].second.second << "!\n";
00189     vcl_pair<unsigned, unsigned> out_p(arr[i].second.first, arr[i].second.second);
00190     out_indices.push_back(out_p);
00191   }
00192 
00193   return true;
00194 }
00195 
00196 
00197 #undef BSTA_SAMPLER_INSTANTIATE
00198 #define BSTA_SAMPLER_INSTANTIATE(T) \
00199 template class bsta_sampler<T >
00200 
00201 #endif // bsta_sampler_txx_