00001 #ifndef INDII_ML_FILTER_KERNELFORWARDBACKWARDSMOOTHER_HPP
00002 #define INDII_ML_FILTER_KERNELFORWARDBACKWARDSMOOTHER_HPP
00003
00004 #include "Smoother.hpp"
00005 #include "ParticleResampler.hpp"
00006 #include "KernelForwardBackwardSmootherModel.hpp"
00007 #include "flags.hpp"
00008 #include "../aux/Almost2Norm.hpp"
00009 #include "../aux/AlmostGaussianKernel.hpp"
00010 #include "../aux/MedianPartitioner.hpp"
00011
00012 namespace indii {
00013 namespace ml {
00014 namespace filter {
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 template <class T = unsigned int,
00056 class NT = Almost2Norm,
00057 class KT = AlmostGaussianKernel,
00058 class ST = MedianPartitioner>
00059 class KernelForwardBackwardSmoother :
00060 public Smoother<T,indii::ml::aux::DiracMixturePdf> {
00061 public:
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 KernelForwardBackwardSmoother(KernelForwardBackwardSmootherModel<T>* model,
00073 const NT& N, const KT& K, const T tT,
00074 const indii::ml::aux::DiracMixturePdf& p_xT);
00075
00076
00077
00078
00079 virtual ~KernelForwardBackwardSmoother();
00080
00081
00082
00083
00084
00085
00086 virtual KernelForwardBackwardSmootherModel<T>* getModel();
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 void smooth(const T tn,
00103 indii::ml::aux::DiracMixturePdf& p_xtn_ytn,
00104 indii::ml::aux::DiracMixturePdf& p_xtnp1_ytn,
00105 indii::ml::aux::Pdf& q_xtn,
00106 const unsigned int flags = 0);
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 void smooth(const T tn,
00123 indii::ml::aux::DiracMixturePdf& p_xtn_ytn,
00124 indii::ml::aux::DiracMixturePdf& p_xtnp1_ytn,
00125 const unsigned int flags = 0);
00126
00127 virtual indii::ml::aux::DiracMixturePdf smoothedMeasure();
00128
00129
00130
00131
00132
00133
00134 indii::ml::aux::DiracMixturePdf& getProposals();
00135
00136
00137
00138
00139
00140
00141 indii::ml::aux::DiracMixturePdf& getPropagations();
00142
00143
00144
00145
00146
00147
00148 void smoothedResample(ParticleResampler* resampler);
00149
00150 private:
00151
00152
00153
00154 KernelForwardBackwardSmootherModel<T>* model;
00155
00156
00157
00158
00159 NT N;
00160
00161
00162
00163
00164 KT K;
00165
00166
00167
00168
00169 unsigned int P;
00170
00171
00172
00173
00174 indii::ml::aux::DiracMixturePdf q_xtns;
00175
00176
00177
00178
00179 indii::ml::aux::vector q_ptns;
00180
00181
00182
00183
00184 indii::ml::aux::DiracMixturePdf q_xtnp1s;
00185
00186
00187
00188
00189 T q_delta;
00190
00191 };
00192
00193 }
00194 }
00195 }
00196
00197 #include "StratifiedParticleResampler.hpp"
00198 #include "../aux/kde.hpp"
00199
00200 #include <assert.h>
00201
00202 template <class T, class NT, class KT, class ST>
00203 indii::ml::filter::KernelForwardBackwardSmoother<T,NT,KT,ST>::KernelForwardBackwardSmoother(
00204 KernelForwardBackwardSmootherModel<T>* model, const NT& N, const KT& K,
00205 const T tT, const indii::ml::aux::DiracMixturePdf& p_xT) :
00206 Smoother<T,indii::ml::aux::DiracMixturePdf>(tT, p_xT),
00207 model(model),
00208 N(N),
00209 K(K),
00210 q_xtns(model->getStateSize()),
00211 q_xtnp1s(model->getStateSize()) {
00212 P = p_xT.getDistributedSize();
00213 }
00214
00215 template <class T, class NT, class KT, class ST>
00216 indii::ml::filter::KernelForwardBackwardSmoother<T,NT,KT,ST>::~KernelForwardBackwardSmoother() {
00217
00218 }
00219
00220 template <class T, class NT, class KT, class ST>
00221 indii::ml::filter::KernelForwardBackwardSmootherModel<T>*
00222 indii::ml::filter::KernelForwardBackwardSmoother<T,NT,KT,ST>::getModel() {
00223 return model;
00224 }
00225
00226 template <class T, class NT, class KT, class ST>
00227 void indii::ml::filter::KernelForwardBackwardSmoother<T,NT,KT,ST>::smooth(
00228 const T tn,
00229 indii::ml::aux::DiracMixturePdf& p_xtn_ytn,
00230 indii::ml::aux::DiracMixturePdf& p_xtnp1_ytn,
00231 indii::ml::aux::Pdf& q_xtn,
00232 const unsigned int flags) {
00233 const unsigned int D = model->getStateSize();
00234
00235
00236 assert (p_xtn_ytn.getDimensions() == D);
00237 assert (p_xtnp1_ytn.getDimensions() == D);
00238 assert (q_xtn.getDimensions() == D);
00239
00240 vector x(D);
00241 const T del = this->tn - tn;
00242 DiracMixturePdf& p_xtnp1_ytT = this->p_xtn_ytT;
00243 unsigned int P_local = aux::shareOf(P);
00244 unsigned int i;
00245
00246
00247 bool sameProposal = flags & SAME_PROPOSAL;
00248 bool samePropagations = flags & SAME_PROPAGATIONS;
00249 bool noResampling = flags & NO_RESAMPLING;
00250 bool noStandardisation = flags & NO_STANDARDISATION;
00251
00252
00253 if (!sameProposal || q_xtns.getSize() == 0) {
00254 q_xtns.clear();
00255 q_ptns.resize(P_local);
00256 for (i = 0; i < P_local; i++) {
00257 noalias(x) = q_xtn.sample();
00258 q_xtns.add(x);
00259 q_ptns(i) = q_xtn.densityAt(x);
00260 }
00261 }
00262
00263
00264 if (!samePropagations || !sameProposal || this->q_delta != del ||
00265 q_xtns.getSize() != q_xtnp1s.getSize()) {
00266 this->q_delta = del;
00267 q_xtnp1s.clear();
00268 for (i = 0; i < q_xtns.getSize(); i++) {
00269 noalias(x) = model->transition(q_xtns.get(i), tn, del);
00270 q_xtnp1s.add(x, q_xtns.getWeight(i));
00271 }
00272 }
00273
00274 aux::vector pi(P_local), delta(P_local), psi(P_local);
00275
00276 if (noStandardisation) {
00277
00278 {
00279
00280 aux::KDTree<ST> queryTree(&q_xtns);
00281 aux::KDTree<ST> targetTree(&p_xtn_ytn);
00282 noalias(pi) = aux::distributedDualTreeDensity(queryTree,
00283 targetTree, p_xtn_ytn.getWeights(), N, K);
00284 }
00285
00286
00287
00288 {
00289 assert (p_xtnp1_ytn.getSize() == p_xtnp1_ytT.getSize());
00290
00291 aux::KDTree<ST> queryTree(&q_xtnp1s);
00292 aux::KDTree<ST> targetTree(&p_xtnp1_ytT);
00293
00294 aux::matrix ws(2,p_xtnp1_ytn.getSize());
00295 row(ws,0) = p_xtnp1_ytT.getWeights();
00296 row(ws,1) = p_xtnp1_ytn.getWeights();
00297
00298 aux::matrix result(2,q_xtnp1s.getSize());
00299 noalias(result) = aux::distributedDualTreeDensity(queryTree,
00300 targetTree, ws, N, K);
00301
00302 noalias(psi) = row(result,0);
00303 noalias(delta) = row(result,1);
00304 }
00305 } else {
00306
00307 {
00308 aux::vector mu(D);
00309 aux::lower_triangular_matrix L(D,D);
00310 noalias(mu) = p_xtn_ytn.getDistributedExpectation();
00311 noalias(L) = p_xtn_ytn.getDistributedStandardDeviation();
00312
00313 DiracMixturePdf q(q_xtns);
00314 q.standardise(mu, L);
00315 p_xtn_ytn.standardise(mu, L);
00316
00317
00318 aux::KDTree<ST> queryTree(&q);
00319 aux::KDTree<ST> targetTree(&p_xtn_ytn);
00320 noalias(pi) = aux::distributedDualTreeDensity(queryTree,
00321 targetTree, p_xtn_ytn.getWeights(), N, K);
00322 }
00323
00324
00325 {
00326 aux::vector mu(D);
00327 aux::lower_triangular_matrix L(D,D);
00328 noalias(mu) = p_xtnp1_ytT.getDistributedExpectation();
00329 noalias(L) = p_xtnp1_ytT.getDistributedStandardDeviation();
00330
00331 DiracMixturePdf q(q_xtnp1s);
00332 q.standardise(mu, L);
00333 p_xtnp1_ytT.standardise(mu, L);
00334
00335
00336 aux::KDTree<ST> queryTree(&q);
00337 aux::KDTree<ST> targetTree(&p_xtnp1_ytT);
00338 noalias(psi) = aux::distributedDualTreeDensity(queryTree,
00339 targetTree, p_xtnp1_ytT.getWeights(), N, K);
00340 }
00341
00342
00343 {
00344 aux::vector mu(D);
00345 aux::lower_triangular_matrix L(D,D);
00346 noalias(mu) = p_xtnp1_ytn.getDistributedExpectation();
00347 noalias(L) = p_xtnp1_ytn.getDistributedStandardDeviation();
00348
00349 DiracMixturePdf q(q_xtnp1s);
00350 q.standardise(mu, L);
00351 p_xtnp1_ytn.standardise(mu, L);
00352
00353
00354 aux::KDTree<ST> queryTree(&q);
00355 aux::KDTree<ST> targetTree(&p_xtnp1_ytn);
00356 noalias(delta) = aux::distributedDualTreeDensity(queryTree,
00357 targetTree, p_xtnp1_ytn.getWeights(), N, K);
00358 }
00359 }
00360
00361
00362 psi = element_div(element_prod(pi,psi), element_prod(delta,q_ptns));
00363 this->p_xtn_ytT = q_xtns;
00364 this->p_xtn_ytT.setWeights(psi);
00365
00366
00367
00368 this->p_xtn_ytT.distributedNormalise();
00369
00370
00371 this->tn = tn;
00372 }
00373
00374 template <class T, class NT, class KT, class ST>
00375 void indii::ml::filter::KernelForwardBackwardSmoother<T,NT,KT,ST>::smooth(
00376 const T tn,
00377 indii::ml::aux::DiracMixturePdf& p_xtn_ytn,
00378 indii::ml::aux::DiracMixturePdf& p_xtnp1_ytn,
00379 const unsigned int flags) {
00380 const unsigned int D = model->getStateSize();
00381
00382
00383 assert (p_xtn_ytn.getDimensions() == D);
00384 assert (p_xtnp1_ytn.getDimensions() == D);
00385
00386 vector x(D);
00387 const T del = this->tn - tn;
00388 DiracMixturePdf& p_xtnp1_ytT = this->p_xtn_ytT;
00389 unsigned int P_local = p_xtn_ytn.getSize();
00390 unsigned int i;
00391
00392
00393 bool noResampling = flags & NO_RESAMPLING;
00394 bool noStandardisation = flags & NO_STANDARDISATION;
00395 bool filterSmoother = flags & FILTER_SMOOTHER;
00396
00397 q_xtns = p_xtn_ytn;
00398 if (noResampling && noStandardisation && filterSmoother) {
00399
00400 q_xtnp1s = p_xtnp1_ytT;
00401 assert (p_xtn_ytn.getSize() == p_xtnp1_ytT.getSize());
00402
00403 aux::vector psi(p_xtnp1_ytT.getWeights());
00404 this->p_xtn_ytT = p_xtn_ytn;
00405 this->p_xtn_ytT.setWeights(psi);
00406
00407
00408 this->tn = tn;
00409
00410 return;
00411 } else if (noResampling) {
00412
00413 q_xtnp1s = p_xtnp1_ytT;
00414 assert (p_xtn_ytn.getSize() == p_xtnp1_ytT.getSize());
00415 } else {
00416
00417 this->q_delta = del;
00418 q_xtnp1s.clear();
00419 for (i = 0; i < p_xtn_ytn.getSize(); i++) {
00420 noalias(x) = model->transition(p_xtn_ytn.get(i), tn, del);
00421 q_xtnp1s.add(x, p_xtn_ytn.getWeight(i));
00422 }
00423 }
00424
00425 const aux::vector& pi = p_xtn_ytn.getWeights();
00426 aux::vector delta(P_local), psi(P_local);
00427
00428 if (noStandardisation) {
00429
00430
00431 assert (p_xtnp1_ytn.getSize() == p_xtnp1_ytT.getSize());
00432
00433 if (noResampling) {
00434
00435 aux::KDTree<ST> tree(&p_xtnp1_ytT);
00436
00437 aux::matrix ws(2,p_xtnp1_ytn.getSize());
00438 row(ws,0) = p_xtnp1_ytT.getWeights();
00439 row(ws,1) = p_xtnp1_ytn.getWeights();
00440
00441 aux::matrix result(2,p_xtnp1_ytn.getSize());
00442 noalias(result) = aux::distributedSelfTreeDensity(tree, ws, N, K,
00443 false);
00444
00445 noalias(psi) = row(result,0);
00446 noalias(delta) = row(result,1);
00447 } else {
00448
00449
00450 assert (p_xtnp1_ytn.getSize() == p_xtnp1_ytT.getSize());
00451
00452
00453
00454 aux::KDTree<ST> queryTree(&q_xtnp1s);
00455 aux::KDTree<ST> targetTree(&p_xtnp1_ytT);
00456
00457 aux::matrix ws(2,p_xtnp1_ytn.getSize());
00458 row(ws,0) = p_xtnp1_ytT.getWeights();
00459 row(ws,1) = p_xtnp1_ytn.getWeights();
00460
00461 aux::matrix result(2,q_xtnp1s.getSize());
00462 noalias(result) = aux::distributedDualTreeDensity(queryTree,
00463 targetTree, ws, N, K);
00464
00465 noalias(psi) = row(result,0);
00466 noalias(delta) = row(result,1);
00467 }
00468 } else {
00469
00470 {
00471 aux::vector mu(D);
00472 aux::lower_triangular_matrix L(D,D);
00473 noalias(mu) = p_xtnp1_ytT.getDistributedExpectation();
00474 noalias(L) = p_xtnp1_ytT.getDistributedStandardDeviation();
00475 p_xtnp1_ytT.standardise(mu, L);
00476
00477
00478 if (noResampling) {
00479
00480 aux::KDTree<ST> tree(&p_xtnp1_ytT);
00481 noalias(delta) = aux::distributedSelfTreeDensity(tree,
00482 p_xtnp1_ytT.getWeights(), N, K);
00483 } else {
00484 DiracMixturePdf q(q_xtnp1s);
00485 q.standardise(mu, L);
00486
00487 aux::KDTree<ST> queryTree(&q);
00488 aux::KDTree<ST> targetTree(&p_xtnp1_ytT);
00489 noalias(delta) = aux::distributedDualTreeDensity(queryTree,
00490 targetTree, p_xtnp1_ytT.getWeights(), N, K);
00491 }
00492 }
00493
00494
00495 {
00496 aux::vector mu(D);
00497 aux::lower_triangular_matrix L(D,D);
00498 noalias(mu) = p_xtnp1_ytn.getDistributedExpectation();
00499 noalias(L) = p_xtnp1_ytn.getDistributedStandardDeviation();
00500 p_xtnp1_ytn.standardise(mu, L);
00501
00502
00503 if (noResampling) {
00504
00505 aux::KDTree<ST> tree(&p_xtnp1_ytn);
00506 noalias(delta) = aux::distributedSelfTreeDensity(tree,
00507 p_xtnp1_ytn.getWeights(), N, K);
00508 } else {
00509 DiracMixturePdf q(q_xtnp1s);
00510 q.standardise(mu, L);
00511
00512 aux::KDTree<ST> queryTree(&q);
00513 aux::KDTree<ST> targetTree(&p_xtnp1_ytn);
00514 noalias(delta) = aux::distributedDualTreeDensity(queryTree,
00515 targetTree, p_xtnp1_ytn.getWeights(), N, K);
00516 }
00517 }
00518 }
00519
00520
00521 psi = element_div(element_prod(pi,psi), delta);
00522 this->p_xtn_ytT = p_xtn_ytn;
00523 this->p_xtn_ytT.setWeights(psi);
00524
00525
00526
00527 this->p_xtn_ytT.distributedNormalise();
00528
00529
00530 this->tn = tn;
00531 }
00532
00533 template <class T, class NT, class KT, class ST>
00534 inline indii::ml::aux::DiracMixturePdf&
00535 indii::ml::filter::KernelForwardBackwardSmoother<T,NT,KT,ST>::getProposals() {
00536 return q_xtns;
00537 }
00538
00539 template <class T, class NT, class KT, class ST>
00540 inline indii::ml::aux::DiracMixturePdf&
00541 indii::ml::filter::KernelForwardBackwardSmoother<T,NT,KT,ST>::getPropagations() {
00542 return q_xtnp1s;
00543 }
00544
00545 template <class T, class NT, class KT, class ST>
00546 indii::ml::aux::DiracMixturePdf
00547 indii::ml::filter::KernelForwardBackwardSmoother<T,NT,KT,ST>::smoothedMeasure() {
00548 namespace aux = indii::ml::aux;
00549
00550 unsigned int i;
00551 StratifiedParticleResampler resampler;
00552 aux::DiracMixturePdf resampled(resampler.resample(
00553 this->getSmoothedState()));
00554 indii::ml::aux::DiracMixturePdf p_ytn_xtT(model->getMeasurementSize());
00555
00556 for (i = 0; i < resampled.getSize(); i++) {
00557 p_ytn_xtT.add(model->measure(resampled.get(i)));
00558 }
00559
00560 return p_ytn_xtT;
00561 }
00562
00563 template <class T, class NT, class KT, class ST>
00564 void indii::ml::filter::KernelForwardBackwardSmoother<T,NT,KT,ST>::smoothedResample(
00565 ParticleResampler* resampler) {
00566 indii::ml::aux::DiracMixturePdf resampled(resampler->resample(
00567 this->getSmoothedState()));
00568 this->setSmoothedState(resampled);
00569 }
00570
00571 #endif