00001 /************************************************************************ 00002 * Copyright (C) 2012 Eindhoven University of Technology (TU/e). * 00003 * All rights reserved. * 00004 ************************************************************************ 00005 * Redistribution and use in source and binary forms, with or without * 00006 * modification, are permitted provided that the following conditions * 00007 * are met: * 00008 * * 00009 * 1. Redistributions of source code must retain the above * 00010 * copyright notice, this list of conditions and the following * 00011 * disclaimer. * 00012 * * 00013 * 2. Redistributions in binary form must reproduce the above * 00014 * copyright notice, this list of conditions and the following * 00015 * disclaimer in the documentation and/or other materials * 00016 * provided with the distribution. * 00017 * * 00018 * THIS SOFTWARE IS PROVIDED BY TU/e "AS IS" AND ANY EXPRESS OR * 00019 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * 00020 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * 00021 * ARE DISCLAIMED. IN NO EVENT SHALL TU/e OR CONTRIBUTORS BE LIABLE * 00022 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 00024 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 00025 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 00026 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 00028 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 00029 * DAMAGE. * 00030 * * 00031 * The views and conclusions contained in the software and * 00032 * documentation are those of the authors and should not be * 00033 * interpreted as representing official policies, either expressed or * 00034 * implied, of TU/e. * 00035 ************************************************************************/ 00036 00037 #include "problib/pdfs/Mixture.h" 00038 00039 using namespace pbl; 00040 00041 Mixture::Mixture() : PDF(-1, PDF::MIXTURE), ptr_(0) { 00042 } 00043 00044 Mixture::Mixture(const Mixture& orig) : PDF(orig), ptr_(orig.ptr_){ 00045 if (ptr_) { 00046 ++ptr_->n_ptrs_; 00047 } 00048 } 00049 00050 Mixture::~Mixture() { 00051 if (ptr_) { 00052 --ptr_->n_ptrs_; 00053 00054 if (ptr_->n_ptrs_ == 0) { 00055 delete ptr_; 00056 } 00057 } 00058 } 00059 00060 Mixture& Mixture::operator=(const Mixture& other) { 00061 if (this != &other) { 00062 if (ptr_) { 00063 --ptr_->n_ptrs_; 00064 if (ptr_->n_ptrs_ == 0) { 00065 delete ptr_; 00066 } 00067 } 00068 ptr_ = other.ptr_; 00069 ++ptr_->n_ptrs_; 00070 00071 dimensions_ = other.dimensions_; 00072 } 00073 return *this; 00074 } 00075 00076 Mixture* Mixture::clone() const { 00077 return new Mixture(*this); 00078 } 00079 00080 void Mixture::cloneStruct() { 00081 if (ptr_->n_ptrs_ > 1) { 00082 --ptr_->n_ptrs_; 00083 ptr_ = new MixtureStruct(*ptr_); 00084 } 00085 } 00086 00087 double Mixture::getLikelihood(const PDF& pdf) const { 00088 assert_msg(ptr_, "Mixture does not contain components."); 00089 assert(ptr_->num_components_ > 0); 00090 assert(ptr_->weights_total_ == 1); 00091 00092 double likelihood = 0; 00093 std::vector<double>::const_iterator it_w =ptr_-> weights_.begin(); 00094 for (std::vector<PDF*>::const_iterator it_pdf = ptr_->components_.begin(); it_pdf != ptr_->components_.end(); ++it_pdf) { 00095 likelihood += (*it_w) * (*it_pdf)->getLikelihood(pdf); 00096 ++it_w; 00097 } 00098 return likelihood; 00099 } 00100 00101 void Mixture::clear() { 00102 if (ptr_) { 00103 --ptr_->n_ptrs_; 00104 if (ptr_->n_ptrs_ == 0) { 00105 delete ptr_; 00106 } 00107 ptr_ = 0; 00108 } 00109 } 00110 00111 double Mixture::getMaxDensity() const { 00112 assert_msg(false, "Mixture does not contain components."); 00113 return 0; 00114 } 00115 00116 int Mixture::components() const { 00117 return ptr_->num_components_; 00118 } 00119 00120 void Mixture::addComponent(const PDF& pdf, double w) { 00121 if (dimensions_ < 0) { 00122 dimensions_ = pdf.dimensions(); 00123 } else { 00124 assert(dimensions_ == pdf.dimensions()); 00125 } 00126 00127 if (!ptr_) { 00128 ptr_ = new MixtureStruct(); 00129 } else { 00130 cloneStruct(); 00131 } 00132 00133 ptr_->components_.push_back(pdf.clone()); 00134 ptr_->weights_.push_back(w); 00135 ptr_->weights_total_ += w; 00136 ++ptr_->num_components_; 00137 } 00138 00139 const PDF& Mixture::getComponent(int i) const { 00140 assert_msg(ptr_, "Mixture does not contain components."); 00141 return *(ptr_->components_[i]); 00142 } 00143 00144 double Mixture::getWeight(int i) const { 00145 assert_msg(ptr_, "Mixture does not contain components."); 00146 return ptr_->weights_[i]; 00147 } 00148 00149 void Mixture::normalizeWeights() { 00150 assert_msg(ptr_, "Mixture does not contain components."); 00151 00152 if (ptr_->weights_total_ == 1) return; 00153 00154 assert(ptr_->weights_total_ > 0); 00155 00156 for (std::vector<double>::iterator it_w = ptr_->weights_.begin(); it_w != ptr_->weights_.end(); ++it_w) { 00157 (*it_w) /= ptr_->weights_total_; 00158 } 00159 ptr_->weights_total_ = 1; 00160 } 00161 00162 std::string Mixture::toString(const std::string& indent) const { 00163 if (!ptr_) { 00164 return "MIX(-)"; 00165 } 00166 00167 std::string new_indent = indent + " "; 00168 00169 std::stringstream ss; 00170 ss << "MIX{\n"; 00171 std::vector<double>::const_iterator it_w = ptr_->weights_.begin(); 00172 for (std::vector<PDF*>::const_iterator it_pdf = ptr_->components_.begin(); it_pdf != ptr_->components_.end(); ++it_pdf) { 00173 ss << new_indent << (*it_w) << " : " << (*it_pdf)->toString(new_indent) << "\n"; 00174 ++it_w; 00175 } 00176 ss << indent << "}"; 00177 return ss.str(); 00178 }