00001 #ifndef INDII_ML_AUX_STANDARDMIXTUREPDF_HPP
00002 #define INDII_ML_AUX_STANDARDMIXTUREPDF_HPP
00003
00004 #include "MixturePdf.hpp"
00005
00006 namespace indii {
00007 namespace ml {
00008 namespace aux {
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 template <class T>
00022 class StandardMixturePdf : public MixturePdf<T> {
00023 public:
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 StandardMixturePdf();
00034
00035
00036
00037
00038
00039
00040
00041 StandardMixturePdf(const unsigned int N);
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 StandardMixturePdf(const T& x, const double w = 1.0);
00053
00054
00055
00056
00057 virtual ~StandardMixturePdf();
00058
00059 virtual void setDimensions(const unsigned int N,
00060 const bool preserve = false);
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 virtual const symmetric_matrix& getCovariance();
00078
00079
00080
00081
00082
00083
00084 symmetric_matrix getDistributedCovariance();
00085
00086 protected:
00087 virtual void dirty();
00088
00089 private:
00090
00091
00092
00093 symmetric_matrix sigma;
00094
00095
00096
00097
00098 symmetric_matrix Zsigma;
00099
00100
00101
00102
00103 bool haveSigma;
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 void calculateCovariance();
00120
00121
00122
00123
00124 template<class Archive>
00125 void save(Archive& ar, const unsigned int version) const;
00126
00127
00128
00129
00130 template<class Archive>
00131 void load(Archive& ar, const unsigned int version);
00132
00133
00134
00135
00136 BOOST_SERIALIZATION_SPLIT_MEMBER()
00137 friend class boost::serialization::access;
00138
00139 };
00140
00141 }
00142 }
00143 }
00144
00145 #include "boost/serialization/base_object.hpp"
00146
00147 namespace ublas = boost::numeric::ublas;
00148
00149 template <class T>
00150 indii::ml::aux::StandardMixturePdf<T>::StandardMixturePdf() :
00151 indii::ml::aux::MixturePdf<T>(0), sigma(0), Zsigma(0) {
00152 haveSigma = false;
00153 }
00154
00155 template <class T>
00156 indii::ml::aux::StandardMixturePdf<T>::StandardMixturePdf(
00157 const unsigned int N) : indii::ml::aux::MixturePdf<T>(N), sigma(N),
00158 Zsigma(N) {
00159 haveSigma = false;
00160 }
00161
00162 template <class T>
00163 indii::ml::aux::StandardMixturePdf<T>::StandardMixturePdf(const T& x,
00164 const double w) : indii::ml::aux::MixturePdf<T>(x.getDimensions()),
00165 sigma(x.getDimensions()), Zsigma(x.getDimensions()) {
00166 haveSigma = false;
00167 add(x, w);
00168 }
00169
00170 template <class T>
00171 indii::ml::aux::StandardMixturePdf<T>::~StandardMixturePdf() {
00172
00173 }
00174
00175 template <class T>
00176 void indii::ml::aux::StandardMixturePdf<T>::setDimensions(
00177 const unsigned int N, const bool preserve) {
00178 MixturePdf<T>::setDimensions(N, preserve);
00179
00180 Zsigma.resize(N, preserve);
00181 sigma.resize(N, preserve);
00182 }
00183
00184 template <class T>
00185 const indii::ml::aux::symmetric_matrix& indii::ml::aux::StandardMixturePdf<
00186 T>::getCovariance() {
00187 if (!haveSigma) {
00188 calculateCovariance();
00189 }
00190 return sigma;
00191 }
00192
00193 template <class T>
00194 indii::ml::aux::symmetric_matrix indii::ml::aux::StandardMixturePdf<
00195 T>::getDistributedCovariance() {
00196 boost::mpi::communicator world;
00197 const unsigned int size = world.size();
00198
00199 if (size == 0) {
00200 return getCovariance();
00201 } else {
00202 const unsigned int N = this->getDimensions();
00203
00204 boost::mpi::communicator world;
00205 matrix Zsigma_d(N,N), sigma_d(N,N);
00206 vector mu_d(N);
00207
00208 if (this->getTotalWeight() > 0.0) {
00209 if (!haveSigma) {
00210 calculateCovariance();
00211 }
00212 } else {
00213 Zsigma.clear();
00214 }
00215
00216 noalias(mu_d) = this->getDistributedExpectation();
00217 noalias(Zsigma_d) = boost::mpi::all_reduce(world, matrix(Zsigma),
00218 std::plus<matrix>());
00219 noalias(sigma_d) = Zsigma_d / this->getDistributedTotalWeight() -
00220 outer_prod(mu_d, mu_d);
00221
00222 return ublas::symmetric_adaptor<matrix, ublas::lower>(sigma_d);
00223 }
00224 }
00225
00226 template <class T>
00227 void indii::ml::aux::StandardMixturePdf<T>::dirty() {
00228 MixturePdf<T>::dirty();
00229 haveSigma = false;
00230 }
00231
00232 template <class T>
00233 void indii::ml::aux::StandardMixturePdf<T>::calculateCovariance() {
00234
00235 assert (this->getTotalWeight() > 0.0);
00236
00237 double w;
00238 const vector& mu = this->getExpectation();
00239 unsigned int i;
00240
00241 Zsigma.clear();
00242 for (i = 0; i < this->getSize(); i++) {
00243 w = this->getWeight(i);
00244 const vector& mu_i = this->get(i).getExpectation();
00245 const symmetric_matrix& sigma_i = this->get(i).getCovariance();
00246
00247 noalias(Zsigma) += w * (sigma_i + outer_prod(mu_i, mu_i));
00248 }
00249 noalias(sigma) = Zsigma / this->getTotalWeight() - outer_prod(mu, mu);
00250 haveSigma = true;
00251 }
00252
00253 template <class T>
00254 template <class Archive>
00255 void indii::ml::aux::StandardMixturePdf<T>::save(Archive& ar,
00256 const unsigned int version) const {
00257 ar & boost::serialization::base_object<
00258 indii::ml::aux::MixturePdf<T> >(*this);
00259 }
00260
00261 template <class T>
00262 template <class Archive>
00263 void indii::ml::aux::StandardMixturePdf<T>::load(Archive& ar,
00264 const unsigned int version) {
00265 ar & boost::serialization::base_object<
00266 indii::ml::aux::MixturePdf<T> >(*this);
00267
00268 sigma.resize(this->getDimensions(), false);
00269 Zsigma.resize(this->getDimensions(), false);
00270 haveSigma = false;
00271 }
00272
00273 #endif
00274