Empirical
StateGrid.h
Go to the documentation of this file.
1 
20 #ifndef EMP_EVO_STATE_GRID_H
21 #define EMP_EVO_STATE_GRID_H
22 
23 #include <map>
24 #include <string>
25 
26 #include "../base/assert.h"
27 #include "../base/Ptr.h"
28 #include "../base/vector.h"
29 
30 #include "../tools/BitVector.h"
31 #include "../tools/File.h"
32 #include "../tools/map_utils.h"
33 #include "../tools/math.h"
34 #include "../tools/Random.h"
35 
36 namespace emp {
37 
39  class StateGridInfo {
40  protected:
41 
43  struct StateInfo {
44  int state_id;
45  char symbol;
46  double score_change;
47  std::string name;
48  std::string desc;
49 
50  StateInfo(int _id, char _sym, double _change,
51  const std::string & _name, const std::string & _desc)
52  : state_id(_id), symbol(_sym), score_change(_change), name(_name), desc(_desc) { ; }
53  StateInfo(const StateInfo &) = default;
54  StateInfo(StateInfo &&) = default;
55  ~StateInfo() { ; }
56 
57  StateInfo & operator=(const StateInfo &) = default;
58  StateInfo & operator=(StateInfo &&) = default;
59  };
60 
62 
63  std::map<int, size_t> state_map;
64  std::map<char, size_t> symbol_map;
65  std::map<std::string, size_t> name_map;
66 
67  size_t GetKey(int state_id) const { return Find(state_map, state_id, 0); }
68  size_t GetKey(char symbol) const { return Find(symbol_map, symbol, 0); }
69  size_t GetKey(const std::string & name) const { return Find(name_map, name, 0); }
70  public:
71  StateGridInfo() : states(), state_map(), symbol_map(), name_map() { ; }
72  StateGridInfo(const StateGridInfo &) = default;
73  StateGridInfo(StateGridInfo &&) = default;
75 
76  StateGridInfo & operator=(const StateGridInfo &) = default;
77  StateGridInfo & operator=(StateGridInfo &&) = default;
78 
79  size_t GetNumStates() const { return states.size(); }
80 
81  // Convert from state ids...
82  char GetSymbol(int state_id) const { return states[ GetKey(state_id) ].symbol; }
83  double GetScoreChange(int state_id) const { return states[ GetKey(state_id) ].score_change; }
84  const std::string & GetName(int state_id) const { return states[ GetKey(state_id) ].name; }
85  const std::string & GetDesc(int state_id) const { return states[ GetKey(state_id) ].desc; }
86 
87  // Convert to state ids...
88  int GetState(char symbol) const {
89  emp_assert( states.size() > GetKey(symbol), states.size(), symbol, (int) symbol );
90  return states[ GetKey(symbol) ].state_id;
91  }
92  int GetState(const std::string & name) const { return states[ GetKey(name) ].state_id; }
93 
94  void AddState(int id, char symbol, double mult=1.0, std::string name="", std::string desc="") {
95  size_t key_id = states.size();
96  states.emplace_back(id, symbol, mult, name, desc);
97  state_map[id] = key_id;
98  symbol_map[symbol] = key_id;
99  name_map[name] = key_id;
100  }
101 
102  };
103 
105  class StateGrid {
106  protected:
107  size_t width;
108  size_t height;
111 
112  public:
113  StateGrid() : width(0), height(0), states(0), info() { ; }
114  StateGrid(StateGridInfo & _i, size_t _w=1, size_t _h=1, int init_val=0)
115  : width(_w), height(_h), states(_w*_h,init_val), info(_i) { ; }
116  StateGrid(StateGridInfo & _i, const std::string & filename)
117  : width(1), height(1), states(), info(_i) { Load(filename); }
118  StateGrid(const StateGrid &) = default;
119  StateGrid(StateGrid && in) = default;
120  ~StateGrid() { ; }
121 
122  StateGrid & operator=(const StateGrid &) = default;
123  StateGrid & operator=(StateGrid &&) = default;
124 
125  size_t GetWidth() const { return width; }
126  size_t GetHeight() const { return height; }
127  size_t GetSize() const { return states.size(); }
128  const emp::vector<int> GetStates() const { return states; }
129  const StateGridInfo & GetInfo() const { return info; }
130 
131  int & operator()(size_t x, size_t y) {
132  emp_assert(x < width, x, width);
133  emp_assert(y < height, y, height);
134  return states[y*width+x];
135  }
136  int operator()(size_t x, size_t y) const {
137  emp_assert(x < width, x, width);
138  emp_assert(y < height, y, height);
139  return states[y*width+x];
140  }
141  int GetState(size_t x, size_t y) const {
142  emp_assert(x < width, x, width);
143  emp_assert(y < height, y, height);
144  return states[y*width+x];
145  }
146  int GetState(size_t id) const { return states[id]; }
147  StateGrid & SetState(size_t x, size_t y, int in) {
148  emp_assert(x < width, x, width);
149  emp_assert(y < height, y, height);
150  states[y*width+x] = in;
151  return *this;
152  }
153  char GetSymbol(size_t x, size_t y) const {
154  emp_assert(x < width, x, width);
155  emp_assert(y < height, y, height);
156  return info.GetSymbol(GetState(x,y));
157  }
158  double GetScoreChange(size_t x, size_t y) const {
159  emp_assert(x < width, x, width);
160  emp_assert(y < height, y, height);
161  return info.GetScoreChange(GetState(x,y));
162  }
163  const std::string & GetName(size_t x, size_t y) const {
164  emp_assert(x < width, x, width);
165  emp_assert(y < height, y, height);
166  return info.GetName(GetState(x,y));
167  }
168 
170  emp::BitVector IsState(int target_state) {
171  emp::BitVector sites(states.size());
172  for (size_t i = 0; i < states.size(); i++) sites[i] = (states[i] == target_state);
173  return sites;
174  }
175 
177  template <typename... Ts>
178  void AddState(Ts &&... args) { info.AddState(std::forward<Ts>(args)...); }
179 
181  template <typename... Ts>
182  StateGrid & Load(Ts &&... args) {
183  std::cout << "Loading!" << std::endl;
184 
185  // Load this data from a stream or a file.
186  File file(std::forward<Ts>(args)...);
187  file.RemoveWhitespace();
188 
189  // Determine the size of the new grid.
190  height = file.GetNumLines();
191  emp_assert(height > 0);
192  width = file[0].size();
193  emp_assert(width > 0);
194 
195  // Now that we have the new size, resize the state grid.
196  size_t size = width * height;
197  states.resize(size);
198 
199  // Load in the specific states.
200  for (size_t row = 0; row < height; row++) {
201  emp_assert(file[row].size() == width); // Make sure all rows are the same size.
202  for (size_t col = 0; col < width; col++) {
203  states[row*width+col] = info.GetState(file[row][col]);
204  }
205  }
206 
207  return *this;
208  }
209 
211  template <typename... Ts>
212  const StateGrid & Print(std::ostream & os=std::cout) const {
213  std::string out(width*2-1, ' ');
214  for (size_t i = 0; i < height; i++) {
215  out[0] = info.GetSymbol( states[i*width] );
216  for (size_t j = 1; j < width; j++) {
217  out[j*2] = info.GetSymbol( states[i*width+j] );
218  }
219  os << out << std::endl;
220  }
221  return *this;
222  }
223 
225  template <typename... Ts>
226  const StateGrid & Write(Ts &&... args) const {
227  File file;
228  std::string out;
229  for (size_t i = 0; i < height; i++) {
230  out.resize(0);
231  out += info.GetSymbol( states[i*width] );
232  for (size_t j = 1; j < width; j++) {
233  out += ' ';
234  out +=info.GetSymbol( states[i*width+j] );
235  }
236  file.Append(out);
237  }
238  file.Write(std::forward<Ts>(args)...);
239  return *this;
240  }
241  };
242 
245  protected:
246  struct State {
247  size_t x;
248  size_t y;
249  int facing;
250 
251  State(size_t _x=0, size_t _y=0, size_t _f=1) : x(_x), y(_y), facing((int)_f) { ; }
252  bool IsAt(size_t _x, size_t _y) const { return x == _x && y == _y; }
253  };
254 
256  bool track_moves;
258 
259  // --- Helper Functions ---
260 
262  void UpdateHistory() { if (track_moves) history.push_back(cur_state); }
263 
265  void MoveX(const StateGrid & grid, int steps=1) {
266  emp_assert(grid.GetWidth(), grid.GetWidth());
267  cur_state.x = (size_t) Mod(steps + (int) cur_state.x, (int) grid.GetWidth());
268  }
269 
271  void MoveY(const StateGrid & grid, int steps=1) {
272  emp_assert(grid.GetHeight(), grid.GetHeight());
273  cur_state.y = (size_t) Mod(steps + (int) cur_state.y, (int) grid.GetHeight());
274  }
275 
276  public:
277  StateGridStatus() : cur_state(0,0,1), track_moves(false) { ; }
278  StateGridStatus(const StateGridStatus &) = default;
279  StateGridStatus(StateGridStatus &&) = default;
280 
281  StateGridStatus & operator=(const StateGridStatus &) = default;
282  StateGridStatus & operator=(StateGridStatus &&) = default;
283 
284  size_t GetX() const { return cur_state.x; }
285  size_t GetY() const { return cur_state.y; }
286  size_t GetFacing() const {
287  emp_assert(cur_state.facing >= 0 && cur_state.facing < 8);
288  return (size_t) cur_state.facing;
289  }
290 
291  bool IsAt(size_t x, size_t y) const { return cur_state.IsAt(x,y); }
292  bool WasAt(size_t x, size_t y) const {
293  for (const State & state : history) if (state.IsAt(x,y)) return true;
294  return false;
295  }
296 
298  emp::BitVector GetVisited(const StateGrid & grid) const {
299  emp::BitVector at_array(grid.GetSize());
300  for (const State & state : history) {
301  size_t pos = state.x + grid.GetWidth() * state.y;
302  at_array.Set(pos);
303  }
304  return at_array;
305  }
306 
307  StateGridStatus & TrackMoves(bool track=true) {
308  bool prev = track_moves;
309  track_moves = track;
310  if (!prev && track_moves) history.push_back(cur_state);
311  else history.resize(0);
312  return *this;
313  }
314 
315  StateGridStatus & Set(size_t _x, size_t _y, size_t _f) {
316  cur_state.x = _x;
317  cur_state.y = _y;
318  cur_state.facing = (int) _f;
319  UpdateHistory();
320  return *this;
321  }
322  StateGridStatus & SetX(size_t _x) { cur_state.x = _x; UpdateHistory(); return *this; }
323  StateGridStatus & SetY(size_t _y) { cur_state.y = _y; UpdateHistory(); return *this; }
324  StateGridStatus & SetPos(size_t _x, size_t _y) {
325  cur_state.x = _x;
326  cur_state.y = _y;
327  UpdateHistory();
328  return *this;
329  }
330  StateGridStatus & SetFacing(size_t _f) { cur_state.facing = (int) _f; UpdateHistory(); return *this; }
331 
333  void Move(const StateGrid & grid, int steps=1) {
334  // std::cout << "steps = " << steps
335  // << " facing = " << cur_state.facing
336  // << " start = (" << cur_state.x << "," << cur_state.y << ")";
337  switch (cur_state.facing) {
338  case 0: MoveX(grid, -steps); MoveY(grid, -steps); break;
339  case 1: MoveY(grid, -steps); break;
340  case 2: MoveX(grid, +steps); MoveY(grid, -steps); break;
341  case 3: MoveX(grid, +steps); break;
342  case 4: MoveX(grid, +steps); MoveY(grid, +steps); break;
343  case 5: MoveY(grid, +steps); break;
344  case 6: MoveX(grid, -steps); MoveY(grid, +steps); break;
345  case 7: MoveX(grid, -steps); break;
346  }
347  UpdateHistory();
348  // std::cout << " end = (" << cur_state.x << "," << cur_state.y << ")"
349  // << " facing = " << cur_state.facing
350  // << std::endl;
351  }
352 
354  void Rotate(int turns=1) {
355  cur_state.facing = Mod(cur_state.facing + turns, 8);
356  UpdateHistory();
357  }
358 
360  void Randomize(const StateGrid & grid, Random & random) {
361  Set(random.GetUInt(grid.GetWidth()), random.GetUInt(grid.GetHeight()), random.GetUInt(8));
362  }
363 
365  int Scan(const StateGrid & grid) {
366  return grid(cur_state.x, cur_state.y);
367  // @CAO: Should we be recording the scan somehow in history?
368  }
369 
371  void SetState(StateGrid & grid, int new_state) {
372  grid.SetState(cur_state.x, cur_state.y, new_state);
373  }
374 
376  void PrintHistory(StateGrid & grid, std::ostream & os=std::cout) const {
377  emp_assert(history.size(), "You can only print history of a StateGrid if you track it!");
378  const size_t width = grid.GetWidth();
379  const size_t height = grid.GetHeight();
380  std::string out(width*2-1, ' ');
381  for (size_t i = 0; i < height; i++) {
382  for (size_t j = 1; j < width; j++) {
383  out[j*2] = grid.GetSymbol(j,i);
384  if (WasAt(j,i)) out[j*2] = '*';
385  }
386  os << out << std::endl;
387  }
388  }
389  };
390 
391 }
392 
393 #endif
StateGridInfo()
Definition: StateGrid.h:71
void Randomize(const StateGrid &grid, Random &random)
Move the current status to a random position and orientation.
Definition: StateGrid.h:360
void Move(const StateGrid &grid, int steps=1)
Move in the direction currently faced.
Definition: StateGrid.h:333
size_t x
X-coordinate of this agent.
Definition: StateGrid.h:247
int Scan(const StateGrid &grid)
Examine state of current position.
Definition: StateGrid.h:365
void PrintHistory(StateGrid &grid, std::ostream &os=std::cout) const
Print the history of an organim moving around a state grid.
Definition: StateGrid.h:376
size_t height
Height of the overall grid.
Definition: StateGrid.h:108
emp::vector< int > states
Specific states at each position in the grid.
Definition: StateGrid.h:109
Information about a particular agent on a state grid.
Definition: StateGrid.h:244
emp::BitVector GetVisited(const StateGrid &grid) const
Get a BitVector indicating the full history of which positions this organism has traversed.
Definition: StateGrid.h:298
StateGridStatus & Set(size_t _x, size_t _y, size_t _f)
Definition: StateGrid.h:315
Information about what a particular state type means in a state grid.
Definition: StateGrid.h:43
size_t GetKey(const std::string &name) const
Definition: StateGrid.h:69
int GetState(const std::string &name) const
Definition: StateGrid.h:92
emp::vector< State > history
All previous positions and facings in this path.
Definition: StateGrid.h:257
char GetSymbol(size_t x, size_t y) const
Definition: StateGrid.h:153
StateGridInfo info
Information about the set of states used in this grid.
Definition: StateGrid.h:110
int GetState(size_t x, size_t y) const
Definition: StateGrid.h:141
const std::string & GetName(size_t x, size_t y) const
Definition: StateGrid.h:163
void UpdateHistory()
If we are tracking moves, store the current position in the history.
Definition: StateGrid.h:262
A class to maintin files for loading, writing, storing, and easy access to components.
Definition: File.h:32
A versatile and non-patterned pseudo-random-number generator (Mersenne Twister).
Definition: ce_random.h:52
const StateGrid & Print(std::ostream &os=std::cout) const
Print the current status of the StateGrid to an output stream.
Definition: StateGrid.h:212
double GetScoreChange(int state_id) const
Definition: StateGrid.h:83
A drop-in replacement for std::vector<bool>, but with extra bitwise logic features.
Definition: BitVector.h:39
StateGrid()
Definition: StateGrid.h:113
void push_back(PB_Ts &&...args)
Definition: vector.h:189
void SetState(StateGrid &grid, int new_state)
Set the current position in the state grid.
Definition: StateGrid.h:371
~StateGrid()
Definition: StateGrid.h:120
A StateGrid describes a map of grid positions to the current state of each position.
Definition: StateGrid.h:105
char GetSymbol(int state_id) const
Definition: StateGrid.h:82
StateGrid & SetState(size_t x, size_t y, int in)
Definition: StateGrid.h:147
size_t width
Width of the overall grid.
Definition: StateGrid.h:107
double GetScoreChange(size_t x, size_t y) const
Definition: StateGrid.h:158
StateInfo & operator=(const StateInfo &)=default
File & Append(const std::string &line)
Append a new line to the end of the file.
Definition: File.h:84
bool IsAt(size_t _x, size_t _y) const
Definition: StateGrid.h:252
size_t size() const
Definition: vector.h:151
void emplace_back(ARGS &&...args)
Definition: vector.h:219
Definition: StateGrid.h:246
int GetState(size_t id) const
Definition: StateGrid.h:146
constexpr uint32_t GetUInt(const uint32_t max)
Definition: ce_random.h:191
size_t GetKey(char symbol) const
Definition: StateGrid.h:68
emp::vector< StateInfo > states
All available states. Position is key ID.
Definition: StateGrid.h:61
size_t GetKey(int state_id) const
Definition: StateGrid.h:67
std::map< int, size_t > state_map
Map of state_id to key ID (state_id can be < 0)
Definition: StateGrid.h:63
bool track_moves
Should we record every move made by this organism?
Definition: StateGrid.h:256
File & Write(std::ostream &output)
Write this file to a provided output stream.
Definition: File.h:153
void AddState(int id, char symbol, double mult=1.0, std::string name="", std::string desc="")
Definition: StateGrid.h:94
const StateGridInfo & GetInfo() const
Definition: StateGrid.h:129
void MoveX(const StateGrid &grid, int steps=1)
Move explicitly in the x direction (regardless of facing).
Definition: StateGrid.h:265
auto Find(const MAP_T &in_map, const KEY_T &key, const typename MAP_T::mapped_type &dval)
Definition: map_utils.h:29
StateGrid(StateGridInfo &_i, const std::string &filename)
Definition: StateGrid.h:116
void AddState(Ts &&...args)
Setup the StateGridInfo with possible states.
Definition: StateGrid.h:178
size_t GetNumLines() const
How many lines are in this file?
Definition: File.h:60
static const PrintStr endl("<br>")
Pre-define emp::endl to insert a "<br>" and thus acting like a newline.
constexpr int Mod(int in_val, int mod_val)
% is actually remainder; Mod is a proper modulus command that handles negative #&#39;s correctly ...
Definition: math.h:26
double score_change
Change ammount for organism score by stepping on this square.
Definition: StateGrid.h:46
std::string name
Name of this state.
Definition: StateGrid.h:47
int GetState(char symbol) const
Definition: StateGrid.h:88
StateGrid & Load(Ts &&...args)
Load in the contents of a StateGrid using the file information provided.
Definition: StateGrid.h:182
size_t GetSize() const
Definition: StateGrid.h:127
int & operator()(size_t x, size_t y)
Definition: StateGrid.h:131
const std::string & GetName(int state_id) const
Definition: StateGrid.h:84
int facing
0=UL, 1=Up, 2=UR, 3=Right, 4=DR, 5=Down, 6=DL, 7=Left (+=Clockwise)
Definition: StateGrid.h:249
void resize(size_t new_size)
Definition: vector.h:161
Full information about the states available in a state grid and meanings of each state.
Definition: StateGrid.h:39
StateGridStatus & SetPos(size_t _x, size_t _y)
Definition: StateGrid.h:324
StateGrid(StateGridInfo &_i, size_t _w=1, size_t _h=1, int init_val=0)
Definition: StateGrid.h:114
std::map< char, size_t > symbol_map
Map of symbols to associated key ID.
Definition: StateGrid.h:64
void Rotate(int turns=1)
Rotate starting from current facing.
Definition: StateGrid.h:354
char symbol
Symbol for printing this state.
Definition: StateGrid.h:45
size_t size() const
Compatibility with size()
Definition: File.h:63
size_t GetX() const
Definition: StateGrid.h:284
std::map< std::string, size_t > name_map
Map of names to associated key ID.
Definition: StateGrid.h:65
If we are in emscripten, make sure to include the header.
Definition: array.h:37
size_t GetY() const
Definition: StateGrid.h:285
State(size_t _x=0, size_t _y=0, size_t _f=1)
Definition: StateGrid.h:251
State cur_state
Position and facing currently used.
Definition: StateGrid.h:255
Build a debug wrapper emp::vector around std::vector.
Definition: vector.h:42
int operator()(size_t x, size_t y) const
Definition: StateGrid.h:136
StateGridStatus & TrackMoves(bool track=true)
Definition: StateGrid.h:307
size_t GetNumStates() const
Definition: StateGrid.h:79
#define emp_assert(...)
Definition: assert.h:199
bool WasAt(size_t x, size_t y) const
Definition: StateGrid.h:292
~StateInfo()
Definition: StateGrid.h:55
StateGridStatus & SetY(size_t _y)
Definition: StateGrid.h:323
size_t GetHeight() const
Definition: StateGrid.h:126
size_t GetFacing() const
Definition: StateGrid.h:286
const StateGrid & Write(Ts &&...args) const
Store the current status of the StateGrid to a file.
Definition: StateGrid.h:226
size_t y
Y-coordinate of this agent.
Definition: StateGrid.h:248
const std::string & GetDesc(int state_id) const
Definition: StateGrid.h:85
StateGridStatus()
Definition: StateGrid.h:277
StateInfo(int _id, char _sym, double _change, const std::string &_name, const std::string &_desc)
Definition: StateGrid.h:50
~StateGridInfo()
Definition: StateGrid.h:74
const emp::vector< int > GetStates() const
Definition: StateGrid.h:128
File & RemoveWhitespace(bool keep_newlines=true)
Delete all whitespace; by default keep newlines.
Definition: File.h:209
void MoveY(const StateGrid &grid, int steps=1)
Move explicitly in the y direction (regardless of facing).
Definition: StateGrid.h:271
StateGridStatus & SetX(size_t _x)
Definition: StateGrid.h:322
StateGridStatus & SetFacing(size_t _f)
Definition: StateGrid.h:330
std::string desc
Explanation of this state.
Definition: StateGrid.h:48
size_t GetWidth() const
Definition: StateGrid.h:125
int state_id
Ordinal id for this state.
Definition: StateGrid.h:44
emp::BitVector IsState(int target_state)
Return a BitVector indicating which positions in the state grid have a particular state...
Definition: StateGrid.h:170
bool IsAt(size_t x, size_t y) const
Definition: StateGrid.h:291