This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/smc/sampling/CumulativeSampler.h
2017-11-15 17:46:06 +01:00

101 lines
3.2 KiB
C++

#ifndef CUMULATIVESAMPLER_H
#define CUMULATIVESAMPLER_H
#include <vector>
#include <memory>
#include <algorithm>
#include "../Particle.h"
#include "ParticleTrajectorieSampler.h"
namespace SMC {
/**
* drawing trajectories using a cumulative drawer
*/
template <typename State>
class CumulativeSampler : public ParticleTrajectorieSampler<State> {
public:
/** ctor */
CumulativeSampler(){
}
/** draw a single particle */
Particle<State> drawSingleParticle(std::vector<Particle<State>> const& particles){
// ensure the copy vector has the same size as the real particle vector
std::vector<Particle<State>> particlesCopy;
particlesCopy.resize(particles.size());
// swap both vectors
particlesCopy = particles;
// calculate cumulative weight
double cumWeight = 0;
for (uint32_t i = 0; i < particles.size(); ++i) {
cumWeight += particlesCopy[i].weight;
particlesCopy[i].weight = cumWeight;
}
return draw(cumWeight, particlesCopy, particles);
}
/** draw a trajectorie of n particles */
std::vector<Particle<State>> drawTrajectorie(std::vector<Particle<State>> const& particles, const int numRealizations){
// ensure the copy vector has the same size as the real particle vector
std::vector<Particle<State>> particlesCopy;
particlesCopy.reserve(particles.size());
particlesCopy = particles;
// calculate cumulative weight
double cumWeight = 0;
for (uint32_t i = 0; i < particles.size(); ++i) {
cumWeight += particlesCopy[i].weight;
particlesCopy[i].weight = cumWeight;
}
// now draw the initial weights and therefore the corresponding particles
std::vector<Particle<State>> trajectorie;
trajectorie.reserve(numRealizations);
for (uint32_t i = 0; i < numRealizations; ++i) {
trajectorie.push_back(draw(cumWeight, particlesCopy, particles));
}
return trajectorie;
}
private:
/** function for drawing particles */
Particle<State> draw(const double cumWeight, std::vector<Particle<State>> const& cumParticles, std::vector<Particle<State>> const& origParticles){
// random value between [0;1]
const double rand01 = double(rand()) / double(RAND_MAX);
// random value between [0; cumulativeWeight]
const double rand = rand01 * cumWeight;
// search comparator
auto comp = [] (const Particle<State>& s, const double d) {return s.weight < d;};
auto it = std::lower_bound(cumParticles.begin(), cumParticles.end(), rand, comp);
//get the idx for the iterator it. this is the same as std::distance(..,..)
int idx = it - cumParticles.begin();
//get the original weight instead of the cumulative weight
Particle<State> drawnParticle = *it;
drawnParticle.weight = origParticles[idx].weight;
return drawnParticle;
}
};
}
#endif // ARTIFICIALDISTRIBUTION_H