Go to the documentation of this file.00001
00002 #ifndef vpdt_mixture_of_h_
00003 #define vpdt_mixture_of_h_
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <vpdl/vpdt/vpdt_dist_traits.h>
00016 #include <vpdl/vpdt/vpdt_probability.h>
00017 #include <vcl_cassert.h>
00018 #include <vcl_vector.h>
00019 #include <vcl_algorithm.h>
00020 #include <vcl_memory.h>
00021
00022
00023 template<class dist_t> class vpdt_mixture_of;
00024
00025 template <class dist>
00026 typename vpdt_dist_traits<vpdt_mixture_of<dist> >::scalar_type
00027 vpdt_box_prob(const vpdt_mixture_of<dist>& d,
00028 const typename vpdt_dist_traits<vpdt_mixture_of<dist> >::field_type& min_pt,
00029 const typename vpdt_dist_traits<vpdt_mixture_of<dist> >::field_type& max_pt);
00030
00031
00032 template <class dist>
00033 struct vpdt_is_mixture<vpdt_mixture_of<dist> >
00034 {
00035 static const bool value = true;
00036 };
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 template<class dist_t>
00047 class vpdt_mixture_of
00048 {
00049 public:
00050
00051 typedef typename dist_t::field_type field_type;
00052
00053 typedef dist_t component_type;
00054
00055
00056 static const unsigned int n = vpdt_field_traits<field_type>::dimension;
00057
00058 typedef typename dist_t::field_type F;
00059
00060 typedef typename vpdt_field_traits<field_type>::scalar_type T;
00061
00062 typedef typename vpdt_field_traits<field_type>::vector_type vector;
00063
00064 typedef typename vpdt_field_traits<field_type>::matrix_type matrix;
00065
00066 private:
00067
00068
00069 struct component
00070 {
00071
00072 component() : distribution(), weight(T(0)) {}
00073
00074 component(const component_type& d, const T& w = T(0) )
00075 : distribution(d), weight(w) {}
00076
00077
00078 bool operator< (const component& rhs) const
00079 { return this->weight > rhs.weight; }
00080
00081
00082
00083
00084 component_type distribution;
00085
00086 T weight;
00087 };
00088
00089
00090
00091 class sort_weight
00092 {
00093 public:
00094 bool operator() (const component* c1, const component* c2) const
00095 { return c1->weight > c2->weight; }
00096 };
00097
00098
00099 template <class comp_type_>
00100 class sort_adaptor
00101 {
00102 public:
00103 sort_adaptor(comp_type_ c) : comp(c) {}
00104 bool operator() (const component* const c1, const component* const c2) const
00105 { return comp(c1->distribution, c1->weight, c2->distribution, c2->weight); }
00106 comp_type_ comp;
00107 };
00108
00109
00110 vcl_vector<component*> components_;
00111
00112 public:
00113
00114 vpdt_mixture_of() {}
00115
00116
00117 vpdt_mixture_of(const vpdt_mixture_of<dist_t>& other)
00118 : components_(other.components_.size(),NULL)
00119 {
00120
00121 for (unsigned int i=0; i<components_.size(); ++i) {
00122 components_[i] = new component(*other.components_[i]);
00123 }
00124 }
00125
00126
00127 ~vpdt_mixture_of()
00128 {
00129 for (unsigned int i=0; i<components_.size(); ++i) {
00130 delete components_[i];
00131 }
00132 }
00133
00134
00135 vpdt_mixture_of<dist_t>& operator= (const vpdt_mixture_of<dist_t>& rhs)
00136 {
00137 if (this != &rhs) {
00138 for (unsigned int i=0; i<components_.size(); ++i) {
00139 delete components_[i];
00140 }
00141 components_.clear();
00142 for (unsigned int i=0; i<rhs.components_.size(); ++i) {
00143 components_.push_back(new component(*rhs.components_[i]));
00144 }
00145 }
00146 return *this;
00147 }
00148
00149
00150 unsigned int dimension() const
00151 {
00152 if (n > 0 || num_components() == 0)
00153 return n;
00154 return components_[0]->distribution.dimension();
00155 }
00156
00157
00158 unsigned int num_components() const { return components_.size(); }
00159
00160
00161 const dist_t& distribution(unsigned int index) const
00162 {
00163 assert(index < num_components());
00164 return components_[index]->distribution;
00165 }
00166
00167
00168 dist_t& distribution(unsigned int index)
00169 {
00170 assert(index < num_components());
00171 return components_[index]->distribution;
00172 }
00173
00174
00175 T weight(unsigned int index) const
00176 {
00177 assert(index < num_components());
00178 return components_[index]->weight;
00179 }
00180
00181
00182 void set_weight(unsigned int index, const T& w)
00183 {
00184 assert(index < num_components());
00185 assert(w >= T(0));
00186 components_[index]->weight = w;
00187 }
00188
00189
00190 bool insert(const dist_t& d, const T& wght = T(0))
00191 {
00192 assert(d.dimension() == this->dimension() || num_components() == 0);
00193 components_.push_back(new component(d, wght));
00194 return true;
00195 }
00196
00197
00198 bool remove_last()
00199 {
00200 if (components_.empty())
00201 return false;
00202 delete components_.back();
00203 components_.pop_back();
00204 return true;
00205 }
00206
00207
00208 T density(const F& pt) const
00209 {
00210 typedef typename vcl_vector<component*>::const_iterator comp_itr;
00211 T prob = 0;
00212 for (comp_itr i = components_.begin(); i != components_.end(); ++i) {
00213
00214 prob += (*i)->weight * (*i)->distribution.prob_density(pt);
00215 }
00216 return prob;
00217 }
00218
00219
00220
00221
00222
00223 T gradient_density(const F& pt, vector& g) const
00224 {
00225 const unsigned int d = this->dimension();
00226 vpdt_set_size(g,d);
00227 vpdt_fill(g,T(0));
00228 typedef typename vcl_vector<component*>::const_iterator comp_itr;
00229 T dens = 0;
00230 for (comp_itr i = components_.begin(); i != components_.end(); ++i) {
00231 vector g_i;
00232 T w_i = (*i)->distribution.norm_const() * (*i)->weight;
00233 dens += w_i * (*i)->distribution.gradient_density(pt,g_i);
00234 g_i *= w_i;
00235 g += g_i;
00236 }
00237 return dens;
00238 }
00239
00240
00241
00242
00243 T cumulative_prob(const F& pt) const
00244 {
00245 typedef typename vcl_vector<component*>::const_iterator comp_itr;
00246 T prob = 0;
00247 T sum_w = 0;
00248 for (comp_itr i = components_.begin(); i != components_.end(); ++i) {
00249 prob += (*i)->weight * (*i)->distribution.cumulative_prob(pt);
00250 sum_w += (*i)->weight;
00251 }
00252 assert(sum_w > T(0));
00253 return prob/sum_w;
00254 }
00255
00256
00257
00258 void compute_mean(F& mean) const
00259 {
00260 const unsigned int d = this->dimension();
00261 vpdt_set_size(mean,d);
00262 vpdt_fill(mean,T(0));
00263
00264 typedef typename vcl_vector<component*>::const_iterator comp_itr;
00265 F cmp_mean;
00266 T sum_w = T(0);
00267 for (comp_itr i = components_.begin(); i != components_.end(); ++i) {
00268 (*i)->distribution.compute_mean(cmp_mean);
00269 cmp_mean *= (*i)->weight;
00270 sum_w += (*i)->weight;
00271 mean += cmp_mean;
00272 }
00273 assert(sum_w > 0);
00274 mean /= sum_w;
00275 }
00276
00277
00278 void compute_covar(matrix& covar) const
00279 {
00280 const unsigned int d = this->dimension();
00281 F mean;
00282 vpdt_set_size(covar,d);
00283 vpdt_fill(covar,T(0));
00284 vpdt_set_size(mean,d);
00285 vpdt_fill(mean,T(0));
00286
00287 typedef typename vcl_vector<component*>::const_iterator comp_itr;
00288 F cmp_mean;
00289 matrix cmp_covar;
00290 T sum_w = T(0);
00291 for (comp_itr i = components_.begin(); i != components_.end(); ++i) {
00292 const T& wgt = (*i)->weight;
00293 (*i)->distribution.compute_covar(cmp_covar);
00294 (*i)->distribution.compute_mean(cmp_mean);
00295 cmp_covar += outer_product(cmp_mean,cmp_mean);
00296 cmp_covar *= wgt;
00297 cmp_mean *= wgt;
00298 sum_w += wgt;
00299 covar += cmp_covar;
00300 mean += cmp_mean;
00301 }
00302 assert(sum_w > 0);
00303 covar -= outer_product(mean,mean);
00304 covar /= sum_w;
00305 }
00306
00307
00308
00309
00310 T norm_const() const
00311 {
00312 typedef typename vcl_vector<component*>::const_iterator comp_itr;
00313 T sum = 0;
00314 for (comp_itr i = components_.begin(); i != components_.end(); ++i)
00315 sum += (*i)->weight;
00316 assert(sum > 0);
00317 return 1/sum;
00318 }
00319
00320
00321 void normalize_weights()
00322 {
00323 typedef typename vcl_vector<component*>::iterator comp_itr;
00324 T norm = norm_const();
00325 for (comp_itr i = components_.begin(); i != components_.end(); ++i)
00326 (*i)->weight *= norm;
00327 }
00328
00329
00330 void sort() { vcl_sort(components_.begin(), components_.end(), sort_weight() ); }
00331
00332
00333 void sort(unsigned int idx1, unsigned int idx2)
00334 { vcl_sort(components_.begin()+idx1, components_.begin()+idx2+1, sort_weight() ); }
00335
00336
00337
00338
00339
00340
00341
00342
00343 template <class comp_type_>
00344 void sort(comp_type_ comp)
00345 { vcl_sort(components_.begin(), components_.end(), sort_adaptor<comp_type_>(comp)); }
00346
00347
00348 template <class comp_type_>
00349 void sort(comp_type_ comp, unsigned int idx1, unsigned int idx2)
00350 { vcl_sort(components_.begin()+idx1, components_.begin()+idx2+1, sort_adaptor<comp_type_>(comp)); }
00351
00352 friend T vpdt_box_prob<dist_t>(const vpdt_mixture_of<dist_t>& d, const F& min_pt, const F& max_pt);
00353 };
00354
00355
00356
00357
00358
00359 template <class dist>
00360 typename vpdt_dist_traits<vpdt_mixture_of<dist> >::scalar_type
00361 vpdt_box_prob(const vpdt_mixture_of<dist>& d,
00362 const typename vpdt_dist_traits<vpdt_mixture_of<dist> >::field_type& min_pt,
00363 const typename vpdt_dist_traits<vpdt_mixture_of<dist> >::field_type& max_pt)
00364 {
00365 typedef typename vpdt_dist_traits<vpdt_mixture_of<dist> >::scalar_type T;
00366 typedef typename vcl_vector<typename vpdt_mixture_of<dist>::component*>::const_iterator comp_itr;
00367 T prob = 0;
00368 T sum_w = 0;
00369 for (comp_itr i = d.components_.begin(); i != d.components_.end(); ++i) {
00370 prob += (*i)->weight * vpdt_box_prob((*i)->distribution,min_pt,max_pt);
00371 sum_w += (*i)->weight;
00372 }
00373 assert(sum_w > T(0));
00374 return prob/sum_w;
00375 }
00376
00377
00378 #endif // vpdt_mixture_of_h_