Fleet  0.0.9
Inference in the LOT
TopN.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include <set>
5 #include <map>
6 #include "IO.h"
7 #include "Numerics.h"
8 #include "OrderedLock.h"
9 
10 #include "FleetArgs.h"
11 #include "OrderedLock.h"
13 
14 
24 template<class T>
25 class TopN : public Serializable<TopN<T>> {
26  using Hypothesis_t = T;
27 
28  OrderedLock lock;
29 
30  const static char SerializationDelimiter = '\n';
31 
32 public:
33  const static size_t MAX_N = SIZE_MAX; // largest N we can have -- useful if we need to store union of everything
34 
35  std::set<T> s;
36  bool print_best; // should we print the best each time we see it?
37  std::atomic<size_t> N;
38 
46  template <typename X, typename = double>
47  struct HasPosterior : std::false_type { };
48  template <typename X>
49  struct HasPosterior <X, decltype((void) X::posterior, 0)> : std::true_type { };
50  //https://stackoverflow.com/questions/1005476/how-to-detect-whether-there-is-a-specific-member-variable-in-class
51 
53 
54  TopN(const TopN<T>& x) {
55  clear();
56  set_size(x.N);
57  set_print_best(x.print_best); // must be set before we add!
58  add(x);
59  }
60  TopN(TopN<T>&& x) {
61  set_size(x.N);
62  set_print_best(x.print_best);
63  s = std::move(x.s);
64  }
65 
66  void operator=(const TopN<T>& x) {
67  clear();
69  set_size(x.N);
70  add(x);
71  }
72  void operator=(TopN<T>&& x) {
73  set_print_best(x.print_best);
74  set_size(x.N);
75  s = std::move(x.s);
76  }
77 
78  void set_size(size_t n) {
83  assert((empty() or n >= N) && "*** Settting TopN size to something smaller probably won't do what you want");
84  N = n;
85  }
86  void set_print_best(bool b) {
91  if(N == 0) { CERR "# *** Warning since N=0, TopN will not print the best even though you set_print_best(true)!" ENDL; }
92  print_best = b;
93  }
94 
95  size_t size() const {
101  return s.size();
102  }
103  bool empty() const {
109  return s.size() == 0;
110  }
111 
112  const std::set<T>& values() const {
118  return s;
119  }
120 
121 
127  bool contains(const T& x) const {
128  // TODO: Lock guard?
129  return s.find(x) != s.end();
130  }
131 
137  [[maybe_unused]] bool add(const T& x) {
143  if(N == 0) return false; // if we happen to not store anything
144 
145  // enable this when we use posterior as the variable, we don't add -inf values
146  if constexpr (HasPosterior<T>::value) {
147  if(std::isnan(x.posterior) or x.posterior == -infinity)
148  return false;
149  }
150 
151  std::lock_guard guard(lock);
152 
153  // if we aren't in there and our posterior is better than the worst
154  if(not contains(x)) {
155  if(s.size() < N or (empty() or worst() < x )) { // skip adding if its the worst -- can't call worst_score due to lock
156  T xcpy = x;
157 
158  if(print_best and (empty() or best() < x )) {
159  xcpy.show();
160  }
161 
162  // add this one
163  s.insert(xcpy);
164 
165  // and remove until we are the right size
166  while(s.size() > N) {
167  s.erase(s.begin());
168  }
169 
170  return true; // we added
171  }
172  }
173 
174  return false; // we didn't add
175 
176  }
177 
178  [[maybe_unused]] bool operator<<(const T& x) {
184  return add(x);
185  }
186 
187  void add(const TopN<T>& x) { // add from a whole other topN
193  for(auto& h: x.s){
194  add(h);
195  }
196  }
197  void add(const std::set<T>& x) { // add from a whole other topN
203  for(auto& h: x){
204  add(h);
205  }
206  }
207  void operator<<(const TopN<T>& x) {
208  add(x);
209  }
210 
214  void pop() {
215  if(not empty())
216  s.erase( std::next(s.rbegin()).base() ); // convert reverse iterator to forward to delete https://stackoverflow.com/questions/1830158/how-to-call-erase-with-a-reverse-iterator
217  }
218 
219  const T& best() const {
225  assert( (!s.empty()) && "You tried to get the max from a TopN that was empty");
226  return *s.rbegin();
227  }
228  const T& worst() const {
234  assert( (!s.empty()) && "You tried to get the min from a TopN that was empty");
235  return *s.begin();
236  }
237 
238  double Z(double temp=1.0) { // (can't be const because it locks)
244  double z = -infinity;
245  std::lock_guard guard(lock);
246  for(const auto& x : s)
247  z = logplusexp(z, x.posterior/temp);
248  return z;
249  }
250 
251  void print(std::string prefix="") {
257  for(auto& h : sorted()) {
258  h.show(prefix);
259  }
260  }
261 
266  std::vector<T> sorted(bool increasing=true) const {
267 
268  std::vector<T> v(s.size());
269 
270  std::copy(s.begin(), s.end(), v.begin());
271 
272  std::sort(v.begin(), v.end(), std::less<T>());
273 
274  // this prevents us from having to define operator>
275  // because it should be faster to do std::sort(v.begin(), v.end(), std::greater<T>());
276  if(not increasing) {
277  std::reverse(v.begin(), v.end());
278  }
279 
280  return v;
281  }
282 
283  void clear() {
288  std::lock_guard guard(lock);
289  s.erase(s.begin(), s.end());
290  }
291 
292  template<typename data_t>
293  [[nodiscard]] TopN compute_posterior(data_t& data){
300  // NOTE: Since this modifies the hypotheses, it returns a NEW TopN
301  TopN o(N);
302  for(auto h : values() ){
303  h.compute_posterior(data);
304  o << h;
305  }
306  return o;
307  }
308 
309  virtual std::string serialize() const override {
310  std::string out = str(N);
311  for(auto& h : s) {
312  out += SerializationDelimiter + h.serialize();
313  }
314  return out;
315  }
316 
317  static TopN<T> deserialize(const std::string& s) {
318 
319  TopN<T> out;
320  auto q = split(s, SerializationDelimiter);
321  out.set_size(string_to<size_t>(q.front())); q.pop_front();
322 
323  for(auto& x : q) {
324  out << T::deserialize(x);
325  }
326 
327  return out;
328  }
329 
330 
331 };
332 
333 // Handy to define this so we can put TopN into a set
334 template<typename HYP>
335 void operator<<(std::set<HYP>& s, TopN<HYP>& t){
336  for(auto h: t.values()) {
337  s.insert(h);
338  }
339 }
Definition: OrderedLock.h:16
bool print_best
Definition: TopN.h:36
std::vector< T > sorted(bool increasing=true) const
Sorted values.
Definition: TopN.h:266
void operator=(TopN< T > &&x)
Definition: TopN.h:72
const T & best() const
Definition: TopN.h:219
Definition: Serializable.h:4
std::string reverse(std::string x)
Definition: Strings.h:185
size_t size() const
Definition: TopN.h:95
std::deque< std::string > split(const std::string &s, const char delimiter)
Split is returns a deque of s split up at the character delimiter. It handles these special cases: sp...
Definition: str.h:50
void set_size(size_t n)
Definition: TopN.h:78
static TopN< T > deserialize(const std::string &s)
Definition: TopN.h:317
bool operator<<(const T &x)
Definition: TopN.h:178
const std::set< T > & values() const
Definition: TopN.h:112
unsigned long ntop
Definition: FleetArgs.h:15
const T & worst() const
Definition: TopN.h:228
TopN compute_posterior(data_t &data)
Definition: TopN.h:293
std::string str(BindingTree *t)
Definition: BindingTree.h:195
void pop()
Pops off the top – you usually won&#39;t want to do this and it&#39;s not efficient.
Definition: TopN.h:214
void clear()
Definition: TopN.h:283
TopN(TopN< T > &&x)
Definition: TopN.h:60
Definition: TopN.h:25
void add(const TopN< T > &x)
Definition: TopN.h:187
constexpr double infinity
Definition: Numerics.h:20
A FIFO mutex (from stackoverflow) https://stackoverflow.com/questions/14792016/creating-a-lock-that-p...
T logplusexp(const T a, const T b)
Definition: Numerics.h:131
Definition: TopN.h:47
void print(std::string prefix="")
Definition: TopN.h:251
#define CERR
Definition: IO.h:23
void set_print_best(bool b)
Definition: TopN.h:86
static const size_t MAX_N
Definition: TopN.h:33
std::set< T > s
Definition: TopN.h:35
#define ENDL
Definition: IO.h:21
bool add(const T &x)
Adds x to the TopN. This will return true if we added (false otherwise)
Definition: TopN.h:137
bool empty() const
Definition: TopN.h:103
bool contains(const T &x) const
Does this contain x?
Definition: TopN.h:127
bool top_print_best
Definition: FleetArgs.h:37
TopN(size_t n=FleetArgs::ntop)
Definition: TopN.h:52
double Z(double temp=1.0)
Definition: TopN.h:238
virtual std::string serialize() const override
Definition: TopN.h:309
void operator=(const TopN< T > &x)
Definition: TopN.h:66
void add(const std::set< T > &x)
Definition: TopN.h:197
std::atomic< size_t > N
Definition: TopN.h:37
TopN(const TopN< T > &x)
Definition: TopN.h:54