00001 #ifndef INDII_ML_FILTER_AUXILIARYPARTICLERESAMPLER_HPP
00002 #define INDII_ML_FILTER_AUXILIARYPARTICLERESAMPLER_HPP
00003
00004 #include "ParticleResampler.hpp"
00005 #include "ParticleFilter.hpp"
00006
00007 namespace indii {
00008 namespace ml {
00009 namespace filter {
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 template <class T = unsigned int>
00028 class AuxiliaryParticleResampler : public ParticleResampler {
00029 public:
00030
00031
00032
00033
00034
00035
00036
00037
00038 AuxiliaryParticleResampler(ParticleFilter<T>* filter,
00039 const unsigned int P = 0);
00040
00041
00042
00043
00044 virtual ~AuxiliaryParticleResampler();
00045
00046
00047
00048
00049
00050
00051
00052
00053 void setNumParticles(const unsigned int P = 0);
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 void setLookAhead(const T tnp1, const indii::ml::aux::vector& ytnp1);
00069
00070 virtual indii::ml::aux::DiracMixturePdf resample(
00071 indii::ml::aux::DiracMixturePdf& p);
00072
00073 private:
00074
00075
00076
00077 struct reweighted_component {
00078
00079
00080
00081 double w;
00082
00083
00084
00085
00086 double rw;
00087
00088
00089
00090
00091 indii::ml::aux::DiracPdf x;
00092
00093
00094
00095
00096
00097
00098
00099 bool operator<(const reweighted_component& o) const;
00100
00101 };
00102
00103
00104
00105
00106 typedef std::vector<reweighted_component> reweighted_component_vector;
00107
00108
00109
00110
00111 typedef typename reweighted_component_vector::iterator
00112 reweighted_component_iterator;
00113
00114
00115
00116
00117 typedef typename reweighted_component_vector::const_iterator
00118 reweighted_component_const_iterator;
00119
00120
00121
00122
00123 ParticleFilter<T>* filter;
00124
00125
00126
00127
00128 unsigned int P;
00129
00130
00131
00132
00133 T tnp1;
00134
00135
00136
00137
00138 indii::ml::aux::vector ytnp1;
00139
00140 };
00141
00142 }
00143 }
00144 }
00145
00146 template <class T>
00147 indii::ml::filter::AuxiliaryParticleResampler<T>::AuxiliaryParticleResampler(
00148 ParticleFilter<T>* filter, const unsigned int P) : filter(filter), P(P) {
00149
00150 }
00151
00152 template <class T>
00153 indii::ml::filter::AuxiliaryParticleResampler<T>::~AuxiliaryParticleResampler() {
00154
00155 }
00156
00157 template <class T>
00158 void indii::ml::filter::AuxiliaryParticleResampler<T>::setNumParticles(
00159 const unsigned int P) {
00160 this->P = P;
00161 }
00162
00163 template <class T>
00164 void indii::ml::filter::AuxiliaryParticleResampler<T>::setLookAhead(
00165 const T tnp1, const indii::ml::aux::vector& ytnp1) {
00166 this->tnp1 = tnp1;
00167 this->ytnp1.resize(ytnp1.size());
00168 this->ytnp1 = ytnp1;
00169 }
00170
00171 template <class T>
00172 indii::ml::aux::DiracMixturePdf
00173 indii::ml::filter::AuxiliaryParticleResampler<T>::resample(
00174 indii::ml::aux::DiracMixturePdf& p) {
00175 namespace aux = indii::ml::aux;
00176
00177 boost::mpi::communicator world;
00178 const unsigned int rank = world.rank();
00179 const unsigned int size = world.size();
00180
00181 aux::DiracMixturePdf resampled(p.getDimensions());
00182 aux::vector x(p.getDimensions());
00183
00184 ParticleFilterModel<T>* model = filter->getModel();
00185 const T tn = filter->getTime();
00186 const T delta = tnp1 - tn;
00187
00188 unsigned int i;
00189 unsigned int P = this->P;
00190 if (P == 0) {
00191 P = p.getDistributedSize();
00192 }
00193 const unsigned int P_local = p.getSize();
00194
00195 double W_rw;
00196 double W_rws;
00197 double W_rwt;
00198 aux::vector rw(P_local);
00199
00200
00201 W_rw = 0.0;
00202 for (i = 0; i < P_local; i++) {
00203 noalias(x) = model->transition(p.get(i), tn, delta);
00204 rw(i) = model->weight(x, ytnp1) * p.getWeight(i);
00205 W_rw += rw(i);
00206 }
00207
00208
00209 W_rws = boost::mpi::scan(world, W_rw, std::plus<double>());
00210 if (rank == size - 1) {
00211 W_rwt = W_rws;
00212 }
00213 boost::mpi::broadcast(world, W_rwt, size - 1);
00214
00215
00216 double alpha;
00217 if (rank == 0) {
00218 alpha = aux::Random::uniform(0.0, 1.0);
00219 }
00220 boost::mpi::broadcast(world, alpha, 0);
00221
00222
00223 double u = 0.0;
00224 double w, j, rem;
00225
00226 w = W_rwt / P;
00227 rem = fmod(W_rws - W_rw, w);
00228 if (rem >= alpha*w) {
00229 j = 1.0 + alpha - rem/w;
00230 } else {
00231 j = alpha - rem/w;
00232 }
00233
00234 for (i = 0; i < P_local; i++) {
00235 u += rw(i);
00236 while (u >= w * j) {
00237 resampled.add(p.get(i), p.getWeight(i) / rw(i));
00238 j += 1.0;
00239 }
00240 }
00241
00242 resampled.redistributeBySize();
00243
00244 return resampled;
00245 }
00246
00247 template <class T>
00248 bool indii::ml::filter::AuxiliaryParticleResampler<T>::reweighted_component::operator<(
00249 const reweighted_component& o) const {
00250 return this->rw > o.rw;
00251 }
00252
00253 #endif