Fleet  0.0.9
Inference in the LOT
BeamSearch.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "IO.h"
4 #include "Control.h"
5 #include <queue>
6 #include <thread>
7 #include <signal.h>
8 
9 #include "FleetStatistics.h"
11 
12 //#define DEBUG_BEAMSEARCH 1
13 
14 extern volatile sig_atomic_t CTRL_C;
15 
35 template<typename HYP>
37 
38  std::mutex lock;
39 public:
40 
41  static constexpr size_t N = 1000000; // how big is this?
42 
43  static constexpr size_t N_REPS = 10; // how many times do we try randomly filling in to determine priority?
44  static constexpr double PARENT_PENALTY = 1.1;
45  static double temperature;
46  static typename HYP::data_t* data;
47 
48  // the smallest element appears on top of this vector
50 
51  BeamSearch(HYP& h0, typename HYP::data_t* d, double temp) : Q(N) {
52 
53  // set these static members (static so GraphNode can use them without having so many copies)
54  data = d;
55  temperature = temp;
56 
57  // We're going to make sure we don't start on -inf because this value will
58  // get inherited by my kisd for when they use -inf
59  for(size_t i=0;i<1000 and !CTRL_C;i++) {
60  auto g = h0;
61  g.complete();
62 
63  g.compute_posterior(*data);
64 
65  if(g.likelihood > -infinity) {
66  h0.prior = 0.0;
67  h0.likelihood = g.likelihood / temperature;
68  add(h0);
69  break;
70  }
71  }
72 
73  assert(not Q.empty() && "*** You should have pushed a non -inf value into Q above -- are you sure its possible?");
74  }
75 
76  void add(HYP& h) { Q.add(h); }
77  void add(HYP&& h) { Q.add(std::move(h)); }
78 
80 
81  ctl.start();
82  while(ctl.running()) {
83 
84  lock.lock();
85  if(Q.empty()) {
86  lock.unlock();
87  continue; // this is necesssary because we might have more threads than Q to start off.
88  }
89  auto t = Q.best(); Q.pop(); ++FleetStatistics::beam_steps;
90  lock.unlock();
91 
92  #ifdef DEBUG_BEAMSEARCH
93  CERR std::this_thread::get_id() TAB "BeamSearch popped " << t.posterior TAB t.string() ENDL;
94  #endif
95 
96  size_t neigh = t.neighbors();
97  assert(neigh>0 && "*** Your starting state has zero neighbors -- did you remember to give it a LOTHypothesis with an empty value?"); // we should not have put on things with no neighbors
98  for(size_t k=0;k<neigh and ctl.running();k++) {
99  auto v = t.make_neighbor(k);
100 
101  // if v is a terminal, we co_yield
102  // otherwise we
103  if(v.is_evaluable()) {
104 
105  v.compute_posterior(*data);
106 
107  co_yield v;
108  }
109  else {
110  //CERR v.string() ENDL;
111 
112  // We compute a stochastic heuristic by filling in h some number of times and taking the min
113  // we're going to start with the previous likelihood we found -- NOTE That this isn't an admissable
114  // heuristic, and may not even make sense, but seems to work well, meainly in preventing -inf
115  double likelihood = t.likelihood * PARENT_PENALTY; // remember this likelihood is divided by temperature
116  for(size_t i=0;i<N_REPS and not CTRL_C;i++) {
117  auto g = v; g.complete();
118  g.compute_posterior(*data);
119 
120  co_yield g;
121 
122  // this assigns a likelihood as the max of the samples
123  if(not std::isnan(g.likelihood)) {
124  likelihood = std::max(likelihood, g.likelihood / temperature); // temperature must go here
125  }
126  }
127 
128  // now we save this prior and likelihood to v (even though v is a partial tree)
129  // so that it is sorted (defaultly by posterior)
130  v.likelihood = likelihood; // save so we can use next time
131  v.posterior = v.compute_prior() + v.likelihood;
132  //CERR "POST:" TAB v.string() TAB v.posterior TAB likelihood ENDL;
133 
134  add(std::move(v));
135  }
136  }
137 
138  // this condition can't go at the top because of multithreading -- we need each thread to loop in the top when it's
139  // waiting at first for the Q to fill up
140  if(Q.empty()) break;
141  }
142  }
143 
144 
145 
146 
147 };
148 
149 
150 template<typename HYP>
151 typename HYP::data_t* BeamSearch<HYP>::data = nullptr;
152 
153 template<typename HYP>
154 double BeamSearch<HYP>::temperature = 100.0;
volatile sig_atomic_t CTRL_C
const T & best() const
Definition: TopN.h:219
#define TAB
Definition: IO.h:19
Definition: BeamSearch.h:36
void add(HYP &&h)
Definition: BeamSearch.h:77
TopN compute_posterior(data_t &data)
Definition: TopN.h:293
static constexpr size_t N_REPS
Definition: BeamSearch.h:43
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 start()
Definition: Control.h:54
This manages multiple threads for running inference. This requires a subclass to define run_thread...
Definition: Control.h:23
generator< HYP & > run_thread(Control &ctl) override
Definition: BeamSearch.h:79
static constexpr size_t N
Definition: BeamSearch.h:41
constexpr double infinity
Definition: Numerics.h:20
Definition: generator.hpp:21
static double temperature
Definition: BeamSearch.h:45
static HYP::data_t * data
Definition: BeamSearch.h:46
#define CERR
Definition: IO.h:23
std::atomic< uintmax_t > beam_steps(0)
#define ENDL
Definition: IO.h:21
void add(HYP &h)
Definition: BeamSearch.h:76
BeamSearch(HYP &h0, typename HYP::data_t *d, double temp)
Definition: BeamSearch.h:51
TopN< HYP > Q
Definition: BeamSearch.h:49
Definition: ThreadedInferenceInterface.h:22
bool add(const T &x)
Adds x to the TopN. This will return true if we added (false otherwise)
Definition: TopN.h:137
bool running()
Definition: Control.h:63
bool empty() const
Definition: TopN.h:103
static constexpr double PARENT_PENALTY
Definition: BeamSearch.h:44
This class has all the information for running MCMC or MCTS in a little package. It defaultly constru...