summaryrefslogtreecommitdiff
path: root/gi/pf/pf.h
blob: ede7cda83d5266c8cf29e4935b505fd0ee2798fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#ifndef _PF_H_
#define _PF_H_

#include <cassert>
#include <vector>
#include "sampler.h"
#include "prob.h"

template <typename ParticleType>
struct ParticleRenormalizer {
  void operator()(std::vector<ParticleType>* pv) const {
    if (pv->empty()) return;
    prob_t z = prob_t::Zero();
    for (unsigned i = 0; i < pv->size(); ++i)
      z += (*pv)[i].weight;
    assert(z > prob_t::Zero());
    for (unsigned i = 0; i < pv->size(); ++i)
      (*pv)[i].weight /= z;
  }
};

template <typename ParticleType>
struct MultinomialResampleFilter {
  explicit MultinomialResampleFilter(MT19937* rng) : rng_(rng) {}

  void operator()(std::vector<ParticleType>* pv) {
    if (pv->empty()) return;
    std::vector<ParticleType>& ps = *pv;
    SampleSet<prob_t> ss;
    for (int i = 0; i < ps.size(); ++i)
      ss.add(ps[i].weight);
    std::vector<ParticleType> nps; nps.reserve(ps.size());
    const prob_t uniform_weight(1.0 / ps.size());
    for (int i = 0; i < ps.size(); ++i) {
      nps.push_back(ps[rng_->SelectSample(ss)]);
      nps[i].weight = uniform_weight;
    }
    nps.swap(ps);
  }

 private:
  MT19937* rng_;
};

template <typename ParticleType>
struct SystematicResampleFilter {
  explicit SystematicResampleFilter(MT19937* rng) : rng_(rng), renorm_() {}

  void operator()(std::vector<ParticleType>* pv) {
    if (pv->empty()) return;
    renorm_(pv);
    std::vector<ParticleType>& ps = *pv;
    std::vector<ParticleType> nps; nps.reserve(ps.size());
    double lower = 0, upper = 0;
    const double skip = 1.0 / ps.size();
    double u_j = rng_->next() * skip;
    //std::cerr << "u_0: " << u_j << std::endl;
    int j = 0;
    for (unsigned i = 0; i < ps.size(); ++i) {
      upper += ps[i].weight.as_float();
      //std::cerr << "lower: " << lower << " upper: " << upper << std::endl;
      // how many children does ps[i] have?
      while (u_j < lower) { u_j += skip; ++j; }
      while (u_j >= lower && u_j <= upper) {
        assert(j < ps.size());
        nps.push_back(ps[i]);
        u_j += skip;
        //std::cerr << " add u_j=" << u_j << std::endl;
        ++j;
      }
      lower = upper;
    }
    //std::cerr << ps.size() << " " << nps.size() << "\n";
    assert(ps.size() == nps.size());
    //exit(1);
    ps.swap(nps);
  }

 private:
  MT19937* rng_;
  ParticleRenormalizer<ParticleType> renorm_;
};

#endif