Add generation methods to Markov

master
Valentin Ochs 2020-02-09 21:55:55 +01:00
parent 279f95b855
commit 87b239a53c
1 changed files with 44 additions and 0 deletions

View File

@ -1,6 +1,7 @@
#pragma once
#include <limits>
#include <map>
#include <random>
#include <stdlib.h>
#include <vector>
@ -62,7 +63,37 @@ public:
return false;
}
template <typename IT, typename Generator>
T gen(IT iter, size_t size, Generator &g) const {
while (size > order()) {
iter++;
size--;
}
if (size == 0) {
return random_child(g);
}
return gen_impl(iter, size, g, std::bool_constant<(ORDER > 0)>{});
}
protected:
template <typename IT, typename Generator>
T gen_impl(IT iter, size_t size, Generator &g,
std::bool_constant<true>) const {
auto child = children.find(*iter);
if (child == children.end()) {
return random_child(g);
}
return child->second.gen(iter + 1, size - 1, g);
}
template <typename IT, typename Generator>
T gen_impl(IT iter, size_t size, Generator &g,
std::bool_constant<false>) const {
return random_child(g);
}
/* Finds the key or adds it */
typename Children::iterator find(const T &key) {
return children.try_emplace(key).first;
@ -104,6 +135,19 @@ public:
return 0.5 / double(total);
}
}
template <typename Generator> T random_child(Generator &g) const {
std::uniform_int_distribution<size_t> dist(0u, total - 1);
auto val = dist(g);
for (auto &child : children) {
if (val < child.second.total) {
return child.first;
}
val -= child.second.total;
}
return T{};
}
};
/* Leaf of the recursion with just a count */