contrib/mul/mbl/mbl_stochastic_data_collector.txx
Go to the documentation of this file.
00001 // This is mul/mbl/mbl_stochastic_data_collector.txx
00002 #ifndef mbl_stochastic_data_collector_txx_
00003 #define mbl_stochastic_data_collector_txx_
00004 //:
00005 // \file
00006 
00007 #include "mbl_stochastic_data_collector.h"
00008 #include <vcl_string.h>
00009 #include <vsl/vsl_vector_io.h>
00010 #include <vnl/vnl_math.h>
00011 
00012 //=======================================================================
00013 
00014 template <class T>
00015 mbl_stochastic_data_collector<T>::
00016 mbl_stochastic_data_collector()
00017 : samples_(0), nPresented_(0), rand(9667566)
00018 {
00019 }
00020 
00021 //=======================================================================
00022 
00023 template <class T>
00024 mbl_stochastic_data_collector<T>::
00025 mbl_stochastic_data_collector(unsigned n):
00026 samples_(n), nPresented_(0), rand(9667566)
00027 {
00028 }
00029 
00030 //=======================================================================
00031 
00032 template <class T>
00033 mbl_stochastic_data_collector<T>::
00034 ~mbl_stochastic_data_collector()
00035 {
00036 }
00037 //=======================================================================
00038 
00039 //: Clear any stored data
00040 template <class T>
00041 void mbl_stochastic_data_collector<T>::clear()
00042 {
00043   nPresented_ = 0;
00044 }
00045 
00046 //=======================================================================
00047 
00048 //: Set number of samples to be stored
00049 // If not set, the value defaults to 1000.
00050 // Calling this function implicitly calls clean().
00051 template <class T>
00052 void mbl_stochastic_data_collector<T>::set_n_samples(int n)
00053 {
00054   nPresented_ = 0;
00055   samples_.resize(n);
00056 }
00057 
00058 //=======================================================================
00059 
00060 //: Stochastically record given vector.
00061 // The vector will be recorded, and saved with a probability equal to that of
00062 // every other vector presented to this function.
00063 // returns true if it actually stored the value.
00064 template <class T>
00065 void mbl_stochastic_data_collector<T>::record(const T& v)
00066 {
00067   if (nPresented_ < samples_.size())
00068   {
00069     samples_[nPresented_] = v;
00070     nPresented_ ++;
00071   }
00072   else
00073   {
00074     double nSamples = static_cast<double>(samples_.size());
00075     // recalculate probability from scratch each time to avoid accumulation of rounding errors.
00076     double prob = nSamples * nSamples / (nPresented_ * (nSamples+1));
00077     nPresented_ ++;
00078     if (rand.drand64() < prob)
00079       samples_[rand.lrand32(samples_.size() - 1)] = v;
00080   }
00081 }
00082 
00083 //=======================================================================
00084 
00085 //: Force recording of this given value
00086 // This does not increment n_presented()
00087 // Used with next(), to avoid calculating values that will not be stored.
00088 template <class T>
00089 void mbl_stochastic_data_collector<T>::force_record(const T& v)
00090 {
00091   if (nPresented_ < samples_.size())
00092     samples_[nPresented_-1] = v;
00093   else
00094     samples_[rand.lrand32(samples_.size() - 1)] = v;
00095 }
00096 
00097 //=======================================================================
00098 
00099 //: Will decide whether to store the next value
00100 // This will increment n_presented()
00101 // \return true if you should call record_definite() with the next value.
00102 template <class T>
00103 bool mbl_stochastic_data_collector<T>::store_next()
00104 {
00105   if (nPresented_ < samples_.size())
00106   {
00107     nPresented_ ++;
00108     return true;
00109   }
00110   else
00111   {
00112     double nSamples = static_cast<double>(samples_.size());
00113     // recalculate probability from scratch each time
00114     //   to avoid accumulation of rounding errors.
00115     double prob = nSamples * nSamples / (nPresented_ * (nSamples+1));
00116     nPresented_ ++;
00117     if (rand.drand64() < prob)
00118     {
00119       return true;
00120     }
00121     else return false;
00122   }
00123 }
00124 
00125 //=======================================================================
00126 
00127 //: Return object describing stored data
00128 template <class T>
00129 mbl_data_wrapper<T>& mbl_stochastic_data_collector<T>::data_wrapper()
00130 {
00131   v_data_.set(&samples_[0], vnl_math_min((unsigned long) samples_.size(), nPresented_));
00132   return v_data_;
00133 }
00134 
00135 //=======================================================================
00136 
00137 //: Reseed the internal random number generator.
00138 template <class T>
00139 void mbl_stochastic_data_collector<T>::reseed (unsigned long seed)
00140 {
00141   rand.reseed(seed);
00142 }
00143 
00144 //=======================================================================
00145 
00146 template <class T>
00147 bool mbl_stochastic_data_collector<T>::is_class(vcl_string const& s) const
00148 {
00149   return s==mbl_stochastic_data_collector<T>::is_a() || mbl_data_collector<T>::is_class(s);
00150 }
00151 
00152 //=======================================================================
00153 
00154 template <class T>
00155 short mbl_stochastic_data_collector<T>::version_no() const
00156 {
00157   return 1;
00158 }
00159 
00160 //=======================================================================
00161 
00162 template <class T>
00163 mbl_data_collector_base* mbl_stochastic_data_collector<T>::clone() const
00164 {
00165   return new mbl_stochastic_data_collector<T>(*this);
00166 }
00167 
00168 //=======================================================================
00169 
00170 template <class T>
00171 void mbl_stochastic_data_collector<T>::print_summary(vcl_ostream& os) const
00172 {
00173   os << "number stored: " << samples_.size()
00174      << ", number presented: " << nPresented_ << '\n';
00175 }
00176 
00177 //=======================================================================
00178 
00179 template <class T>
00180 void mbl_stochastic_data_collector<T>::b_write(vsl_b_ostream& bfs) const
00181 {
00182   vsl_b_write(bfs, version_no());
00183 
00184   vsl_b_write(bfs, samples_);
00185   vsl_b_write(bfs, nPresented_);
00186 }
00187 
00188 //=======================================================================
00189 
00190 template <class T>
00191 void mbl_stochastic_data_collector<T>::b_read(vsl_b_istream& bfs)
00192 {
00193   if (!bfs) return;
00194 
00195   short version;
00196   vsl_b_read(bfs,version);
00197   switch (version)
00198   {
00199   case (1):
00200     vsl_b_read(bfs, samples_);
00201     vsl_b_read(bfs, nPresented_);
00202     break;
00203   default:
00204     vcl_cerr << "I/O ERROR: mbl_stochastic_data_collector<T::b_read(vsl_b_istream&)\n"
00205              << "           Unknown version number "<< version << '\n';
00206     bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00207     return;
00208   }
00209 }
00210 
00211 #define MBL_STOCHASTIC_DATA_COLLECTOR_INSTANTIATE(T) \
00212 VCL_DEFINE_SPECIALIZATION vcl_string mbl_stochastic_data_collector<T >::is_a() const \
00213 {  return vcl_string("mbl_stochastic_data_collector<" #T ">"); }\
00214 template class mbl_stochastic_data_collector< T >
00215 
00216 #endif // mbl_stochastic_data_collector_txx_