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