Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 #include "problib/pdfs/Gaussian.h"
00038 #include "problib/pdfs/Uniform.h"
00039 
00040 using namespace pbl;
00041 
00042 Gaussian::Gaussian(int dim) : PDF(dim, PDF::GAUSSIAN), ptr_(0) {
00043 }
00044 
00045 Gaussian::Gaussian(const arma::vec& mu, const arma::mat& cov) : PDF(mu.n_elem, PDF::GAUSSIAN), ptr_(new GaussianStruct(mu, cov)) {
00046 }
00047 
00048 Gaussian::Gaussian(const Gaussian& orig) : PDF(orig.ptr_->mu_.n_elem, PDF::GAUSSIAN), ptr_(orig.ptr_) {
00049     if (ptr_) {
00050         ++ptr_->n_ptrs_;
00051     }
00052 }
00053 
00054 Gaussian::~Gaussian() {
00055         if (ptr_) {
00056                 --ptr_->n_ptrs_;
00057 
00058                 if (ptr_->n_ptrs_ == 0) {
00059                         delete ptr_;
00060                 }
00061         }
00062 }
00063 
00064 Gaussian& Gaussian::operator=(const Gaussian& other)  {
00065         if (this != &other)  {
00066                 if (ptr_) {
00067                         --ptr_->n_ptrs_;
00068                         if (ptr_->n_ptrs_ == 0) {
00069                                 delete ptr_;
00070                         }
00071                 }
00072                 ptr_ = other.ptr_;
00073                 ++ptr_->n_ptrs_;
00074 
00075                 dimensions_ = other.dimensions_;
00076         }
00077         return *this;
00078 }
00079 
00080 Gaussian* Gaussian::clone() const {
00081         return new Gaussian(*this);
00082 }
00083 
00084 void Gaussian::cloneStruct() {
00085         if (ptr_->n_ptrs_ > 1) {
00086                 --ptr_->n_ptrs_;
00087                 ptr_ = new GaussianStruct(*ptr_);
00088         }
00089 }
00090 
00091 double Gaussian::getLikelihood(const PDF& pdf) const {
00092         CHECK_INITIALIZED
00093 
00094         if (pdf.type() == PDF::GAUSSIAN) {
00095                 const Gaussian* G = static_cast<const pbl::Gaussian*>(&pdf);
00096                 return getDensity(*G);
00097         } else if (pdf.type() == PDF::UNIFORM) {
00098                 const Uniform* U = static_cast<const pbl::Uniform*>(&pdf);
00099         return U->getLikelihood(*this);
00100         }
00101 
00102         assert_msg(false, "Gaussian: Likelihood can only be calculated with another Gaussian or Uniform pdf.");
00103         return 0;
00104 }
00105 
00106 double Gaussian::getDensity(const arma::vec& v, double max_mah_dist) const {
00107         CHECK_INITIALIZED
00108         return getDensity(v, ptr_->mu_, ptr_->cov_, max_mah_dist);
00109 }
00110 
00111 double Gaussian::getDensity(const Gaussian& G, double max_mah_dist) const {
00112         CHECK_INITIALIZED
00113         arma::mat S = G.getCovariance() + ptr_->cov_;
00114         return getDensity(ptr_->mu_, G.getMean(), S);
00115 }
00116 
00117 double Gaussian::getMaxDensity() const {
00118         CHECK_INITIALIZED
00119         return getDensity(ptr_->mu_, ptr_->mu_, ptr_->cov_);
00120 }
00121 
00122 bool Gaussian::getExpectedValue(arma::vec& v) const {
00123         CHECK_INITIALIZED
00124         v = ptr_->mu_;
00125         return true;
00126 }
00127 
00128 double Gaussian::getDensity(const arma::vec& v1, const arma::vec& v2, const arma::mat& S, double max_mah_dist) const {
00129         
00130         assert(v1.n_elem == v2.n_elem && v1.n_elem == S.n_rows);
00131 
00132     double det = arma::det(S);
00133 
00134         
00135         assert(det != 0);
00136 
00137         
00138         arma::vec diff = v2 - v1;
00139 
00140         
00141         double mahalanobis_dist_sq = arma::dot(arma::inv(S) * diff, diff);
00142 
00143         
00144         assert(mahalanobis_dist_sq >= 0);
00145 
00146         
00147         if (max_mah_dist > 0 && mahalanobis_dist_sq > (max_mah_dist * max_mah_dist)) {
00148                 return 0;
00149         }
00150 
00151     double pi2_pow = 1;
00152     for(unsigned int d = 0; d < S.n_rows; ++d) {
00153         pi2_pow *= 2 * M_PI;
00154     }
00155 
00156         
00157     double pos_sqrt_pow = 1 / sqrt(pi2_pow * det);
00158         return exp(-0.5 * mahalanobis_dist_sq) * pos_sqrt_pow;
00159 }
00160 
00161 void Gaussian::setMean(const arma::vec& mu) {
00162         if (ptr_) {
00163                 cloneStruct();
00164         } else {
00165                 ptr_ = new GaussianStruct(mu, arma::zeros(mu.n_elem, mu.n_elem));
00166         }
00167 
00168         ptr_->mu_ = mu;
00169 }
00170 
00171 void Gaussian::setCovariance(const arma::mat& cov) {
00172         if (ptr_) {
00173                 cloneStruct();
00174         } else {
00175                 ptr_ = new GaussianStruct(arma::zeros(cov.n_cols), cov);
00176         }
00177 
00178         ptr_->cov_ = cov;
00179 }
00180 
00181 const arma::vec& Gaussian::getMean() const {
00182         CHECK_INITIALIZED
00183         return ptr_->mu_;
00184 }
00185 
00186 const arma::mat& Gaussian::getCovariance() const {
00187         CHECK_INITIALIZED
00188         return ptr_->cov_;
00189 }
00190 
00191 std::string Gaussian::toString(const std::string& indent) const {
00192         if (!ptr_) {
00193                 return "N(-)";
00194         }
00195 
00196         std::stringstream s;
00197 
00198         s << "N( [";
00199         for(int i = 0; i < dimensions_; ++i) {
00200                 s << " " << ptr_->mu_(i);
00201         }
00202 
00203         s << "], [";
00204         for(int i = 0; i < dimensions_; ++i) {
00205                 for(int j = 0; j < dimensions_; ++j) {
00206                         s << " " << ptr_->cov_(i, j);
00207                 }
00208                 s <<  ";";
00209         }
00210         s << "] )";
00211 
00212         return s.str();
00213 }