Fleet  0.0.9
Inference in the LOT
VirtualMachinePool.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "DiscreteDistribution.h"
5 
6 #include <vector>
7 #include <queue>
8 
9 
14 template<typename VirtualMachineState_t>
16 
18  for(auto& vms : v) {
19  if(vms.status == vmstatus_t::COMPLETE) { // can't add up probability for errors
20  out.addmass(vms.get_output(), vms.lp);
21  }
22  else {
23  assert(false && "*** You should not be computing marginal outcomes with VMS states that didn't complete.");
24  }
25  }
26  return out;
27 }
28 
29 
41 template<typename VirtualMachineState_t>
43 
51  struct compare_VirtualMachineState_t_prt {
52  bool operator()(const VirtualMachineState_t* lhs, const VirtualMachineState_t* rhs) { return lhs->lp < rhs->lp; }
53  };
54 
55 public:
56 
57  typedef typename VirtualMachineState_t::output_t output_t;
58  typedef typename VirtualMachineState_t::input_t input_t;
59 
60  // how many steps have I run so far? -- this needs to be global so that we can keep track of
61  // whether we should push a new state that occurs too late.
62  unsigned long total_vms_steps;
63  double worst_lp;
64  unsigned long total_instruction_count;
65 
66  std::priority_queue<VirtualMachineState_t*, std::vector<VirtualMachineState_t*>, VirtualMachinePool::compare_VirtualMachineState_t_prt> Q; // Q of states sorted by probability
67  //std::priority_queue<VirtualMachineState_t*, ReservedVector<VirtualMachineState_t*,16>, VirtualMachinePool::compare_VirtualMachineState_t_prt> Q; // Does not seem to speed things up
68 
69  VirtualMachinePool() : total_vms_steps(0), worst_lp(infinity), total_instruction_count(0) {
70  }
71 
72 
73  virtual ~VirtualMachinePool() {
74  clear();
75  }
76 
80  virtual void clear() {
81  while(not Q.empty()) {
82  VirtualMachineState_t* vms = Q.top(); Q.pop();
83  delete vms;
84  }
85 
86  total_vms_steps = 0;
87  worst_lp = infinity;
88  }
89 
95  bool wouldIadd(double lp) {
96  // we won't add stuff that's worse than MIN_LP or that will never run
97  // (it will never run if it's lp < worst_lp and we don't have enough steps to get there)
98  return lp > MIN_LP and
99  (Q.size() + total_vms_steps <= MAX_STEPS or lp > worst_lp);
100  }
101 
106  void push(VirtualMachineState_t* o) {
107  if(wouldIadd(o->lp)){ // TODO: might be able to add an optimization here that doesn't push if we don't have enough steps left to get it
108  Q.push(o);
109  worst_lp = std::min(worst_lp, o->lp); //keep track of the worst we've seen
110  }
111  // else nothing
112  }
113 
123  template<typename T>
124  bool copy_increment_push(const VirtualMachineState_t* x, T v, double lpinc) {
125  if(wouldIadd(x->lp + lpinc)) {
126  assert(x->status == vmstatus_t::GOOD);
127  auto s = new VirtualMachineState_t(*x); // copy
128  s->template push<T>(v); // add v
129  s->lp += lpinc;
130  this->push(s);
131  return true;
132  }
133  return false;
134  }
135 
143  template<typename T>
144  bool increment_push(VirtualMachineState_t* s, T v, double lpinc) {
145  if(wouldIadd(s->lp + lpinc)) {
146  assert(s->status == vmstatus_t::GOOD);
147  s->template push<T>(v); // add this
148  s->lp += lpinc;
149  this->push(s);
150  return true;
151  }
152  return false;
153  }
154 
164 
166 
167  total_vms_steps = 0;
168  while(total_vms_steps < MAX_STEPS && out.size() < MAX_OUTPUTS && !Q.empty()) {
169 
170  VirtualMachineState_t* vms = Q.top(); Q.pop();
171  assert(vms->status == vmstatus_t::GOOD);
172 
173  // if we ever go back to the non-pointer version, we might need fanciness to move out of top https://stackoverflow.com/questions/20149471/move-out-element-of-std-priority-queue-in-c11
174  assert(vms->lp >= MIN_LP);
175 
176  total_vms_steps++;
177 
178  auto y = vms->run();
179  //print("!", (int)vms->status, vms->recursion_depth, total_vms_steps);
180 
181  if(vms->status == vmstatus_t::COMPLETE) { // can't add up probability for errors
182  out.addmass(y, vms->lp);
183  total_instruction_count += vms->runtime_counter.total;
184  }
185 
186  // not else if because we need to delete complete ones too
187  if(vms->status != vmstatus_t::RANDOM_CHOICE_NO_DELETE) {
188  total_instruction_count += vms->runtime_counter.total;
189  delete vms; // if our previous copy isn't pushed back on the stack, delete it
190  }
191  else {
192  // else restore to running order when we're RANDOM_CHOICE_NO_DELETE so it keeps running
193  vms->status = vmstatus_t::GOOD;
194  }
195  }
196 
197  // this leaves some in the stack, but they are cleaned up by the destructor
198  // (this way we can resume running if we want to)
199  return out;
200  }
201 
202 
210  std::vector<VirtualMachineState_t> run_vms() {
211 
212  std::vector<VirtualMachineState_t> out;
213 
214  total_vms_steps = 0;
215  while(total_vms_steps < MAX_STEPS && !Q.empty()) {
216 
217  VirtualMachineState_t* vms = Q.top(); Q.pop();
218  assert(vms->status == vmstatus_t::GOOD);
219  assert(vms->lp >= MIN_LP);
220 
221  total_vms_steps++;
222 
223  vms->run();
224 
225  if(vms->status == vmstatus_t::COMPLETE) {
226  out.push_back(*vms);
227  total_instruction_count += vms->runtime_counter.total;
228  }
229 
230  if(vms->status != vmstatus_t::RANDOM_CHOICE_NO_DELETE) {
231  total_instruction_count += vms->runtime_counter.total;
232  delete vms; // if our previous copy isn't pushed back on the stack, delete it
233  }
234  else {
235  // else restore to running order
236  vms->status = vmstatus_t::GOOD;
237  }
238  }
239 
240  return out;
241  }
242 
243 };
static unsigned long MAX_STEPS
Definition: VirtualMachineControl.h:30
Definition: VirtualMachineControl.h:13
void push(VirtualMachineState_t *o)
Add the VirtualMachineState_t o to this pool (but again checking if I&#39;d add)
Definition: VirtualMachinePool.h:106
VirtualMachinePool()
Definition: VirtualMachinePool.h:69
DiscreteDistribution< output_t > run()
This runs and adds up the probability mass for everything, returning a dictionary outcomes->log_proba...
Definition: VirtualMachinePool.h:163
std::priority_queue< VirtualMachineState_t *, std::vector< VirtualMachineState_t * >, VirtualMachinePool::compare_VirtualMachineState_t_prt > Q
Definition: VirtualMachinePool.h:66
virtual void clear()
Remove everything and reset my values.
Definition: VirtualMachinePool.h:80
Definition: DiscreteDistribution.h:25
static double MIN_LP
Definition: VirtualMachineControl.h:36
static unsigned long MAX_OUTPUTS
Definition: VirtualMachineControl.h:33
bool copy_increment_push(const VirtualMachineState_t *x, T v, double lpinc)
This is an important opimization where we will make a copy of x, push v into it&#39;s stack...
Definition: VirtualMachinePool.h:124
constexpr double infinity
Definition: Numerics.h:20
void addmass(T x, double v)
Definition: DiscreteDistribution.h:91
unsigned long total_vms_steps
Definition: VirtualMachinePool.h:62
bool increment_push(VirtualMachineState_t *s, T v, double lpinc)
Same as copy_increment_push, but does not make a copy – just add.
Definition: VirtualMachinePool.h:144
std::vector< VirtualMachineState_t > run_vms()
Run but return a vector of completed virtual machines instead of marginalizing outputs. You might want this if you needed to separate execution paths, or wanted to access runtime counts. This also can get joint distributions on outputs by running a VirtualMachineState multiple times.
Definition: VirtualMachinePool.h:210
VirtualMachineState_t::output_t output_t
Definition: VirtualMachinePool.h:57
This stores a distribution from values of T to log probabilities. It is used as the return value from...
bool wouldIadd(double lp)
Returns true if I would add something with this lp, given my MAX_STEPS and the stack. This lets us speed up by checking if we would add before copying/constructing a VMS.
Definition: VirtualMachinePool.h:95
unsigned long total_instruction_count
Definition: VirtualMachinePool.h:64
size_t size() const
Definition: DiscreteDistribution.h:202
double worst_lp
Definition: VirtualMachinePool.h:63
virtual ~VirtualMachinePool()
Definition: VirtualMachinePool.h:73
DiscreteDistribution< typename VirtualMachineState_t::output_t > marginal_vms_output(std::vector< VirtualMachineState_t > &v)
Compute the marginal output of a collection of VirtualMachineStates (as we might get from run_vms) ...
Definition: VirtualMachinePool.h:15
VirtualMachineState_t::input_t input_t
Definition: VirtualMachinePool.h:58
Definition: VirtualMachinePool.h:42