Go to the documentation of this file.00001
00002 #include "pdf1d_mixture.h"
00003
00004
00005
00006
00007
00008
00009
00010 #include <vcl_cmath.h>
00011 #include <vcl_cstdlib.h>
00012 #include <vcl_string.h>
00013 #include <vsl/vsl_indent.h>
00014 #include <vsl/vsl_binary_loader.h>
00015 #include <pdf1d/pdf1d_mixture_sampler.h>
00016 #include <vcl_cassert.h>
00017 #include <vsl/vsl_vector_io.h>
00018 #include <vnl/vnl_c_vector.h>
00019
00020
00021
00022 void pdf1d_mixture::init()
00023 {
00024 }
00025
00026 pdf1d_mixture::pdf1d_mixture()
00027 {
00028 init();
00029 }
00030
00031 pdf1d_mixture::pdf1d_mixture(const pdf1d_mixture& m):
00032 pdf1d_pdf()
00033 {
00034 init();
00035 *this = m;
00036 }
00037
00038 pdf1d_mixture& pdf1d_mixture::operator=(const pdf1d_mixture& m)
00039 {
00040 if (this==&m) return *this;
00041
00042 delete_stuff();
00043
00044 pdf1d_pdf::operator=(m);
00045
00046 int n = m.component_.size();
00047 component_.resize(n);
00048 for (int i=0;i<n;++i)
00049 component_[i] = m.component_[i]->clone();
00050
00051 weight_ = m.weight_;
00052
00053 return *this;
00054 }
00055
00056
00057
00058
00059 void pdf1d_mixture::delete_stuff()
00060 {
00061 int n = component_.size();
00062 for (int i=0;i<n;++i)
00063 delete component_[i];
00064 component_.resize(0);
00065 weight_.resize(0);
00066 }
00067
00068 pdf1d_mixture::~pdf1d_mixture()
00069 {
00070 delete_stuff();
00071 }
00072
00073
00074
00075 pdf1d_sampler* pdf1d_mixture::new_sampler() const
00076 {
00077 pdf1d_mixture_sampler* i = new pdf1d_mixture_sampler;
00078 i->set_model(*this);
00079
00080 return i;
00081 }
00082
00083
00084 void pdf1d_mixture::init(const pdf1d_pdf& comp_type, int n)
00085 {
00086 delete_stuff();
00087 component_.resize(n);
00088 weight_.resize(n);
00089 for (int i=0;i<n;++i)
00090 {
00091 component_[i] = comp_type.clone();
00092 weight_[i] = 1.0/n;
00093 }
00094 }
00095
00096
00097
00098 void pdf1d_mixture::add_component(const pdf1d_pdf& comp)
00099 {
00100 vcl_vector<pdf1d_pdf*> old_comps = component_;
00101 vcl_vector<double> old_wts = weight_;
00102 unsigned int n = component_.size();
00103 assert(n == weight_.size());
00104
00105 component_.resize(n+1);
00106 weight_.resize(n+1);
00107
00108 for (unsigned int i=0;i<n;++i)
00109 {
00110 component_[i] = old_comps[i];
00111 weight_[i] = old_wts[i];
00112 }
00113
00114 weight_[n] = 0.0;
00115 component_[n] = comp.clone();
00116 }
00117
00118
00119
00120 void pdf1d_mixture::clear()
00121 {
00122 delete_stuff();
00123 }
00124
00125
00126
00127
00128
00129
00130 bool pdf1d_mixture::is_valid_pdf() const
00131 {
00132 if (!pdf1d_pdf::is_valid_pdf()) return false;
00133 const unsigned n = n_components();
00134
00135 if (weight_.size() != n || component_.size() != n || n < 1) return false;
00136
00137 double sum = vnl_c_vector<double>::sum(&weight_[0], n);
00138 if (vcl_fabs(1.0 - sum) > 1e-10 ) return false;
00139
00140 for (unsigned i=0; i<n; ++i)
00141 {
00142 if (!components()[i]->is_valid_pdf()) return false;
00143 }
00144 return true;
00145 }
00146
00147
00148 void pdf1d_mixture::set_mean_and_variance(double m, double v)
00149 {
00150 set_mean(m);
00151 set_variance(v);
00152 }
00153
00154
00155
00156
00157 vcl_string pdf1d_mixture::is_a() const
00158 {
00159 return vcl_string("pdf1d_mixture");
00160 }
00161
00162
00163
00164 bool pdf1d_mixture::is_class(vcl_string const& s) const
00165 {
00166 return pdf1d_pdf::is_class(s) || s==pdf1d_mixture::is_a();
00167 }
00168
00169
00170
00171 short pdf1d_mixture::version_no() const
00172 {
00173 return 1;
00174 }
00175
00176
00177
00178 pdf1d_pdf* pdf1d_mixture::clone() const
00179 {
00180 return new pdf1d_mixture(*this);
00181 }
00182
00183
00184
00185
00186
00187 void pdf1d_mixture::print_summary(vcl_ostream& os) const
00188 {
00189 os<<'\n'<<vsl_indent();
00190 pdf1d_pdf::print_summary(os);
00191 os<<'\n';
00192 for (unsigned int i=0;i<component_.size();++i)
00193 {
00194 os<<vsl_indent()<<"Component "<<i<<" : Wt: "<<weight_[i] <<'\n'
00195 <<vsl_indent()<<"PDF: " << component_[i]<<'\n';
00196 }
00197 }
00198
00199
00200
00201 void pdf1d_mixture::b_write(vsl_b_ostream& bfs) const
00202 {
00203 vsl_b_write(bfs, is_a());
00204 vsl_b_write(bfs, version_no());
00205 pdf1d_pdf::b_write(bfs);
00206 vsl_b_write(bfs, component_);
00207 vsl_b_write(bfs, weight_);
00208 }
00209
00210
00211
00212 void pdf1d_mixture::b_read(vsl_b_istream& bfs)
00213 {
00214 if (!bfs) return;
00215
00216 vcl_string name;
00217 vsl_b_read(bfs,name);
00218 if (name != is_a())
00219 {
00220 vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_mixture &)\n"
00221 << " Attempted to load object of type "
00222 << name <<" into object of type " << is_a() << vcl_endl;
00223 bfs.is().clear(vcl_ios::badbit);
00224 return;
00225 }
00226
00227 delete_stuff();
00228
00229 short version;
00230 vsl_b_read(bfs,version);
00231 switch (version)
00232 {
00233 case (1):
00234 pdf1d_pdf::b_read(bfs);
00235 vsl_b_read(bfs, component_);
00236 vsl_b_read(bfs, weight_);
00237 break;
00238 default:
00239 vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, pdf1d_mixture &)\n"
00240 << " Unknown version number "<< version << vcl_endl;
00241 bfs.is().clear(vcl_ios::badbit);
00242 return;
00243 }
00244 }
00245
00246
00247
00248
00249 double pdf1d_mixture::operator()(double x) const
00250 {
00251 return vcl_exp(log_p(x));
00252 }
00253
00254
00255
00256 double pdf1d_mixture::log_p(double x) const
00257 {
00258 int n = n_components();
00259
00260 vcl_vector<double> log_ps(n);
00261 double max_log_p = 0;
00262 for (int i=0;i<n;++i)
00263 {
00264 if (weight_[i]>0.0)
00265 {
00266 log_ps[i] = component_[i]->log_p(x);
00267 if (i==0 || log_ps[i]>max_log_p) max_log_p = log_ps[i];
00268 }
00269 }
00270
00271 double sum=0.0;
00272
00273 for (int i=0;i<n;i++)
00274 {
00275 if (weight_[i]>0.0)
00276 sum += weight_[i] * vcl_exp(log_ps[i]-max_log_p);
00277 }
00278
00279 return vcl_log(sum) + max_log_p;
00280 }
00281
00282
00283 double pdf1d_mixture::cdf(double x) const
00284 {
00285 double sum = 0;
00286
00287 int n = n_components();
00288 for (int i=0;i<n;++i)
00289 sum += weight_[i]*component_[i]->cdf(x);
00290
00291 return sum;
00292 }
00293
00294
00295 bool pdf1d_mixture::cdf_is_analytic() const
00296 {
00297 return true;
00298 }
00299
00300
00301
00302 double pdf1d_mixture::gradient(double x, double& p) const
00303 {
00304 double p1;
00305 double g1 = component_[0]->gradient(x,p1);
00306 double g = g1*weight_[0];
00307 p = p1*weight_[0];
00308
00309 for (unsigned int i=1;i<n_components();i++)
00310 {
00311 g1 = component_[i]->gradient(x,p1);
00312 g += g1*weight_[i];
00313 double p_comp = p1*weight_[i];
00314 p += p_comp;
00315 }
00316
00317 return g;
00318 }
00319
00320
00321
00322
00323 unsigned pdf1d_mixture::nearest_comp(double x) const
00324 {
00325 assert(component_.size()>=1);
00326
00327 int n = n_components();
00328 if (n==1) return 0;
00329
00330 int best_i=0;
00331 double min_d2 = vcl_fabs(x-component_[0]->mean());
00332
00333 for (int i=1;i<n;i++)
00334 {
00335 double d2 = vcl_fabs(x-component_[i]->mean());
00336 if (d2<min_d2)
00337 {
00338 best_i=i;
00339 min_d2=d2;
00340 }
00341 }
00342
00343 return best_i;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353 double pdf1d_mixture::nearest_plausible(double , double ) const
00354 {
00355 vcl_cerr << "ERROR: pdf1d_mixture::nearest_plausible NYI\n";
00356 vcl_abort();
00357 return 0.0;
00358 }
00359
00360
00361