Fleet  0.0.9
Inference in the LOT
VirtualMachineState.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <type_traits>
4 #include <map>
5 #include <utility>
6 #include <tuple>
7 
8 #include "Errors.h"
9 #include "Program.h"
10 #include "Stack.h"
12 #include "RuntimeCounter.h"
13 #include "VirtualMachineControl.h"
14 
15 #include "VMSRuntimeError.h"
16 
17 // if defined, we do NOT check that the stack sizes are empty at the end.
18 // You might want this if we are using one VirtualMachineState to compute multiple outputs.
19 // NOTE: This is risky because if we mess up something in implementation, this check often
20 // helps to find it
21 //#define NO_CHECK_END_STACK_SIZE 1
22 
23 // These are the only types of classes we are able to memoize in a lexicon
24 // NOTE: We need short because that's the "key" used for LOTHypothesis instead of lexicon
25 #define LEXICON_MEMOIZATION_TYPES short,std::string,int
26 
27 namespace FleetStatistics {}
28 template<typename X> class VirtualMachinePool;
29 extern std::atomic<uintmax_t> FleetStatistics::vm_ops;
30 
44 template<typename _t_input, typename _t_output, typename... VM_TYPES>
46 public:
47 
48  using input_t = _t_input;
49  using output_t = _t_output;
50 
51  using this_t = VirtualMachineState<input_t, output_t, VM_TYPES...>;
52 
53  // Define the function type for instructions and things operating on this VirtualMachineState
54  // This is read a few other places, like in Builtins
55  using FT = std::function<void(this_t*,int)>;
56 
57  // what we use internally for stacks
58  template<typename T>
59  using VMSStack = Stack<T>;
60 
61  //static constexpr double LP_BREAKOUT = 5.0; // we keep executing a probabilistic thread as long as it doesn't cost us more than this compared to the top
62 
63  Program<this_t> program; // programs are instructions for myself
64  VMSStack<input_t> xstack; //xstackthis stores a stack of the x values (for recursive calls)
65  const output_t& err; // what error output do we return? Just a reference to a value for speed
66  double lp; // the probability of this context
67 
68  unsigned long recursion_depth; // when I was created, what was my depth?
69 
70 private:
71  // these are private and should only be accessed via stack(), mem(), memstack() below
72 
73  // This is a little bit of fancy template metaprogramming that allows us to define a stack
74  // like std::tuple<VMSStack<bool>, VMSStack<std::string> > using a list of type names defined in VM_TYPES
75  template<typename... args>
76  struct stack_t { std::tuple<VMSStack<args>...> value; };
77  stack_t<VM_TYPES...> _stack; // our stacks of different types
78 
79  // same for defining memoizaition types -- here these are the only ones we allow
80  template<typename... args>
81  struct mem_t { std::tuple<std::map<std::pair<args,input_t>,output_t>...> value; };
82  mem_t<LEXICON_MEMOIZATION_TYPES> _mem;
83 
84  template<typename... args>
85  struct memstack_t { std::tuple< VMSStack<std::pair<args, input_t>>...> value; };
86  memstack_t<LEXICON_MEMOIZATION_TYPES> _memstack;
87 
88 public:
89 
90  vmstatus_t status; // are we still running? Did we get an error?
91 
92  // what do we use to count up instructions
93  // NOTE for now this may be a bit slower and unnecessary but it doesn't seem so bad at the
94  // moment so this may need to be optimized later to be optional
96 
97  // where we place random flips back onto
99 
100  VirtualMachineState(input_t x, const output_t& e, VirtualMachinePool<this_t>* po) :
101  err(e), lp(0.0), recursion_depth(0), status(vmstatus_t::GOOD), pool(po) {
102  xstack.push(x);
103  }
104 
105  template<typename T>
106  std::map<std::pair<T,input_t>,output_t>& mem() { return std::get<std::map<std::pair<T,input_t>,output_t>>(_mem.value); }
107 
108  template<typename T>
109  VMSStack<std::pair<T,input_t>>& memstack() { return std::get<VMSStack<std::pair<T,input_t>>>(_memstack.value); }
110 
117  bool operator<(const VirtualMachineState& m) const {
118  return lp < m.lp;
119  }
120 
125  template<typename T>
127  static_assert(contains_type<T,VM_TYPES...>() && "*** Error type T missing from VM_TYPES");
128  return std::get<VMSStack<T>>(_stack.value);
129  }
130 
135  template<typename T>
136  const VMSStack<T>& stack() const {
137  static_assert(contains_type<T,VM_TYPES...>() && "*** Error type T missing from VM_TYPES");
138  return std::get<VMSStack<T>>(_stack.value);
139  }
140 
145  template<typename T>
146  T getpop() {
147  static_assert(contains_type<T,VM_TYPES...>() && "*** Error type T missing from VM_TYPES");
148  assert(stack<T>().size() > 0 && "Cannot pop from an empty stack -- this should not happen! Something is likely wrong with your grammar's argument types, return type, or arities.");
149 
150  T x = std::move(stack<T>().top());
151  stack<T>().pop();
152  return x;
153  }
154 
159  template<size_t n, typename...args>
160  auto getpop_nth() {
161  static_assert( n >= 0 and n < sizeof...(args) && "*** Higher n than args.");
162  return getpop<typename std::tuple_element<n, std::tuple<args...> >::type>();
163  }
164 
169  template<typename T>
170  T gettop() {
171  static_assert(contains_type<T,VM_TYPES...>() && "*** Error type T missing from VM_TYPES");
172  assert(stack<T>().size() > 0 && "Cannot gettop from an empty stack -- this should not happen! Something is likely wrong with your grammar's argument types, return type, or arities.");
173  return stack<T>().top();
174  }
175 
176  template<typename T>
177  void push(T& x){
178  static_assert(contains_type<T,VM_TYPES...>() && "*** Error type T missing from VM_TYPES");
183  stack<T>().push(x);
184  }
185  template<typename T>
186  void push(T&& x){
187  static_assert(contains_type<T,VM_TYPES...>() && "*** Error type T missing from VM_TYPES");
188  stack<T>().push(std::move(x));
189  }
190 
191  void push_x(input_t x) {
192  xstack.push(x);
193  }
194 
199  template<typename T, typename... args>
200  bool _exactly_one() const {
201  return (... && ((std::is_same<T,args>::value and stack<T>().size()==1) or stack<args>().empty()));
202  }
203  template<typename T>
204  bool exactly_one() const {
205  return this->_exactly_one<T, VM_TYPES...>();
206  }
207 
212  output_t get_output() {
213 
214  if(status == vmstatus_t::ERROR)
215  return err;
216 
217  assert(status == vmstatus_t::COMPLETE && "*** Probably should not be calling this unless we are complete");
218 
219  #ifndef NO_CHECK_END_STACK_SIZE
220  assert( exactly_one<output_t>() and xstack.size() == 1 and "When we return, all of the stacks should be empty or else something is awry.");
221  #endif
222 
223  return gettop<output_t>();
224  }
225 
235  output_t run() {
236  status = vmstatus_t::GOOD;
237 
238  try {
239 
240  while(status == vmstatus_t::GOOD and (not program.empty()) ) {
241 
242  if(program.size() + runtime_counter.total > MAX_RUN_PROGRAM ) { // if we've run too long or we couldn't possibly finish
243  throw VMSRuntimeError();
244  }
245 
247 
248  Instruction i = program.top(); program.pop();
249 
250  // keep track of what instruction we've run
251  runtime_counter.increment(i);
252 
253  auto f = reinterpret_cast<FT*>(i.f);
254  (*f)(const_cast<this_t*>(this), i.arg);
255 
256  } // end while loop over ops
257 
258  } catch (VMSRuntimeError& e) {
259  // this may be thrown by a primitive
260  status = vmstatus_t::ERROR;
261  }
262 
263  // when we exit, set the status to complete if we are good
264  // otherwise, leave it where it was
265  if(status == vmstatus_t::GOOD) {
266  status = vmstatus_t::COMPLETE;
267  return get_output();
268  }
269  else {
270  // if we get here, there was a problem
271  return err;
272  }
273  }
274 
275 };
Definition: Stack.h:22
void push(T &&x)
Definition: VirtualMachineState.h:186
Definition: VMSRuntimeError.h:13
Definition: VirtualMachineControl.h:13
void push(const T &val)
Push val onto the stack.
Definition: Stack.h:49
void * f
Definition: Instruction.h:24
Definition: VirtualMachineState.h:45
Program< this_t > program
Definition: VirtualMachineState.h:63
VMSStack< std::pair< T, input_t > > & memstack()
Definition: VirtualMachineState.h:109
bool exactly_one() const
Definition: VirtualMachineState.h:204
int arg
Definition: Instruction.h:25
T total
Definition: RuntimeCounter.h:24
Definition: FleetStatistics.h:5
output_t run()
Run with a pointer back to pool p. This is required because "flip" may push things onto the pool...
Definition: VirtualMachineState.h:235
VMSStack< input_t > xstack
Definition: VirtualMachineState.h:64
RuntimeCounter runtime_counter
Definition: VirtualMachineState.h:95
bool _exactly_one() const
There is one element in stack T and the rest are empty. Used to check in returning the output...
Definition: VirtualMachineState.h:200
void increment(Instruction &i, T count=1)
Add count number of items to this instruction&#39;s count.
Definition: RuntimeCounter.h:33
Definition: Instruction.h:20
VirtualMachineState(input_t x, const output_t &e, VirtualMachinePool< this_t > *po)
Definition: VirtualMachineState.h:100
void pop()
Remove top from the stack.
Definition: Stack.h:59
T getpop()
Retrieves and pops the element of type T from the stack.
Definition: VirtualMachineState.h:146
_t_output output_t
Definition: VirtualMachineState.h:49
Instruction top()
Definition: Stack.h:83
double lp
Definition: VirtualMachineState.h:66
vmstatus_t
Definition: VMStatus.h:4
std::atomic< uintmax_t > vm_ops(0)
void push(T &x)
Definition: VirtualMachineState.h:177
bool empty() const
Definition: Stack.h:109
VMSStack< T > & stack()
Returns a reference to the stack (of a given type)
Definition: VirtualMachineState.h:126
T gettop()
Retrieves the top of the stack as a copy and does not remove.
Definition: VirtualMachineState.h:170
std::function< void(this_t *, int)> FT
Definition: VirtualMachineState.h:55
size_t size() const
Definition: Stack.h:105
void push_x(input_t x)
Definition: VirtualMachineState.h:191
bool operator<(const VirtualMachineState &m) const
These must be sortable by lp so that we can enumerate them from low to high probability in a VirtualM...
Definition: VirtualMachineState.h:117
const output_t & err
Definition: VirtualMachineState.h:65
const VMSStack< T > & stack() const
Const reference to top of stack.
Definition: VirtualMachineState.h:136
_t_input input_t
Definition: VirtualMachineState.h:48
This class manages counting operations at runtime and interfaces operations to a grammar NOTE: Curren...
VirtualMachinePool< this_t > * pool
Definition: VirtualMachineState.h:98
Definition: RuntimeCounter.h:16
unsigned long recursion_depth
Definition: VirtualMachineState.h:68
Definition: Program.h:6
output_t get_output()
Return the output and do some checks that the stacks are as they should be if you&#39;re reading the outp...
Definition: VirtualMachineState.h:212
A program here stores just a stack of instructions which can be executed by the VirtualMachineState_t...
std::map< std::pair< T, input_t >, output_t > & mem()
Definition: VirtualMachineState.h:106
auto getpop_nth()
Getpops the n&#39;th element of args (useful for writing primitives)
Definition: VirtualMachineState.h:160
vmstatus_t status
Definition: VirtualMachineState.h:90
Definition: VirtualMachinePool.h:42
Many things in Fleet are stacks and this is designed to allow for rapid changse to the stack type in ...