Evocosm - A C++ Framework for Evolutionary Computing

Main Index

Created by Scott Robert Ladd at Coyote Gulch Productions.


simple_fsm.h
1 //---------------------------------------------------------------------
2 // Algorithmic Conjurings @ http://www.coyotegulch.com
3 // Evocosm -- An Object-Oriented Framework for Evolutionary Algorithms
4 //
5 // simple_fsm.h
6 //---------------------------------------------------------------------
7 //
8 // Copyright 1996, 1999, 2002, 2003, 2004, 2005, 2006, 2007 Scott Robert Ladd
9 //
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the
22 // Free Software Foundation, Inc.
23 // 59 Temple Place - Suite 330
24 // Boston, MA 02111-1307, USA.
25 //
26 //-----------------------------------------------------------------------
27 //
28 // For more information on this software package, please visit
29 // Scott's web site, Coyote Gulch Productions, at:
30 //
31 // http://www.coyotegulch.com
32 //
33 //-----------------------------------------------------------------------
34 
35 #if !defined(LIBEVOCOSM_FSM_H)
36 #define LIBEVOCOSM_FSM_H
37 
38 // Standard C++ Library
39 #include <cstddef>
40 #include <stack>
41 #include <stdexcept>
42 using namespace std;
43 
44 // libevocosm
45 #include "evocommon.h"
46 #include "fsm_tools.h"
47 
48 namespace libevocosm
49 {
51 
59  template <size_t InSize, size_t OutSize>
60  class simple_fsm : protected globals, protected fsm_tools
61  {
62  public:
64  struct tranout_t
65  {
67  size_t m_new_state;
68 
70  size_t m_output;
71  };
72 
74 
78  simple_fsm(size_t a_size);
79 
81 
86  simple_fsm(const simple_fsm<InSize,OutSize> & a_parent1, const simple_fsm<InSize,OutSize> & a_parent2);
87 
89 
93  simple_fsm(const simple_fsm<InSize,OutSize> & a_source);
94 
96 
100  virtual ~simple_fsm();
101 
102  // Assignment
108  simple_fsm & operator = (const simple_fsm<InSize,OutSize> & a_source);
109 
111 
123  void mutate(double a_rate);
124 
126 
132  static void set_mutation_weight(mutation_id a_type, double a_weight);
133 
135 
141  size_t transition(size_t a_input);
142 
144 
147  void reset();
148 
150 
154  size_t size() const;
155 
157 
163  const tranout_t & get_transition(size_t a_state, size_t a_input) const;
164 
166 
170  size_t num_input_states() const;
171 
173 
177  size_t num_output_states() const;
178 
180 
184  size_t init_state() const;
185 
187 
191  size_t current_state() const;
192 
193  private:
194  // release resources
195  void release();
196 
197  // deep copy
198  void deep_copy(const simple_fsm<InSize,OutSize> & a_source);
199 
200  protected:
203 
205  size_t m_init_state;
206 
209 
211  size_t m_size;
212 
214  static mutation_selector g_selector;
215  };
216 
217  // Static initializer
218  template <size_t InSize, size_t OutSize>
220 
221  // release resources
222  template <size_t InSize, size_t OutSize>
224  {
225  for (size_t s = 0; s < m_size; ++s)
226  delete [] m_state_table[s];
227 
228  delete [] m_state_table;
229  }
230 
231  // deep copy
232  template <size_t InSize, size_t OutSize>
233  void simple_fsm<InSize,OutSize>::deep_copy(const simple_fsm<InSize,OutSize> & a_source)
234  {
235  // allocate state table
236  m_state_table = new tranout_t * [m_size];
237 
238  for (size_t s = 0; s < m_size; ++s)
239  {
240  // allocate an array corresponding to inputs
241  m_state_table[s] = new tranout_t [InSize];
242 
243  // set transition values
244  for (size_t i = 0; i < InSize; ++i)
245  {
246  m_state_table[s][i].m_new_state = a_source.m_state_table[s][i].m_new_state;
247  m_state_table[s][i].m_output = a_source.m_state_table[s][i].m_output;
248  }
249  }
250  }
251 
252  // Creation constructor
253  template <size_t InSize, size_t OutSize>
255  : m_state_table(NULL),
256  m_init_state(0),
257  m_current_state(0),
258  m_size(a_size)
259  {
260  // verify parameters
261  if (m_size < 2)
262  throw std::runtime_error("invalid simple_fsm creation parameters");
263 
264  // allocate state table
265  m_state_table = new tranout_t * [m_size];
266 
267  for (size_t s = 0; s < m_size; ++s)
268  {
269  // allocate an array corresponding to inputs
270  m_state_table[s] = new tranout_t [InSize];
271 
272  // set transition values
273  for (size_t i = 0; i < InSize; ++i)
274  {
275  m_state_table[s][i].m_new_state = rand_index(m_size);
276  m_state_table[s][i].m_output = rand_index(OutSize);
277  }
278  }
279 
280  // set initial state and start there
281  m_init_state = rand_index(m_size);
283  }
284 
285  // Construct via bisexual crossover
286  template <size_t InSize, size_t OutSize>
288  : m_state_table(NULL),
289  m_init_state(0),
290  m_current_state(0),
291  m_size(a_parent1.m_size)
292  {
293  // copy first parent
294  deep_copy(a_parent1);
295 
296  // don't do anything else if fsms differ is size
297  if (a_parent1.m_size != a_parent2.m_size)
298  return;
299 
300  // replace states from those in second parent 50/50 chance
301  size_t x = rand_index(m_size);
302 
303  for (size_t n = x; n < m_size; ++n)
304  {
305  // set transition values
306  for (size_t i = 0; i < InSize; ++i)
307  {
308  m_state_table[n][i].m_new_state = a_parent2.m_state_table[n][i].m_new_state;
309  m_state_table[n][i].m_output = a_parent2.m_state_table[n][i].m_output;
310  }
311  }
312 
313  // randomize the initial state (looks like mom and dad but may act like either one!)
314  if (g_random.get_real() < 0.5)
315  m_init_state = a_parent1.m_init_state;
316  else
317  m_init_state = a_parent2.m_init_state;
318 
319  // reset for start
321  }
322 
323  // Copy constructor
324  template <size_t InSize, size_t OutSize>
326  : m_state_table(NULL),
327  m_init_state(a_source.m_init_state),
328  m_current_state(a_source.m_current_state),
329  m_size(a_source.m_size)
330  {
331  // copy first parent
332  deep_copy(a_source);
333  }
334 
335  // Virtual destructor
336  template <size_t InSize, size_t OutSize>
338  {
339  release();
340  }
341 
342  // Assignment
343  template <size_t InSize, size_t OutSize>
345  {
346  // release resources
347  release();
348 
349  // set values
350  m_init_state = a_source.m_init_state;
351  m_current_state = a_source.m_current_state;
352  m_size = a_source.m_size;
353 
354  // copy source
355  deep_copy(a_source);
356 
357  return *this;
358  }
359 
361  template <size_t InSize, size_t OutSize>
363  {
364  g_selector.set_weight(a_type,a_weight);
365  }
366 
367  // Mutation
368  template <size_t InSize, size_t OutSize>
370  {
371  // the number of chances for mutation is based on the number of states in the machine;
372  // larger machines thus encounter more mutations
373  for (size_t n = 0; n < m_size; ++n)
374  {
375  if (g_random.get_real() < a_rate)
376  {
377  // pick a mutation
378  switch (g_selector.get_index())
379  {
380  case MUTATE_OUTPUT_SYMBOL:
381  {
382  // mutate output symbol
383  size_t state = rand_index(m_size);
384  size_t input = rand_index(InSize);
385 
386  size_t choice;
387 
388  do
389  {
390  choice = rand_index(OutSize);
391  }
392  while (m_state_table[state][input].m_output == choice);
393 
394  m_state_table[state][input].m_output = choice;
395  break;
396  }
397  case MUTATE_TRANSITION:
398  {
399  // mutate state transition
400  size_t state = rand_index(m_size);
401  size_t input = rand_index(InSize);
402 
403  size_t choice;
404 
405  do
406  {
407  choice = rand_index(m_size);
408  }
409  while (m_state_table[state][input].m_new_state == choice);
410 
411  m_state_table[state][input].m_new_state = choice;
412  break;
413  }
414  case MUTATE_REPLACE_STATE:
415  {
416  // mutate state transition
417  size_t state = rand_index(m_size);
418 
419  // allocate an array corresponding to inputs
420  delete [] m_state_table[state];
421  m_state_table[state] = new tranout_t [InSize];
422 
423  // set transition values
424  for (size_t i = 0; i < InSize; ++i)
425  {
426  m_state_table[state][i].m_new_state = rand_index(m_size);
427  m_state_table[state][i].m_output = rand_index(OutSize);
428  }
429 
430  break;
431  }
432  case MUTATE_SWAP_STATES:
433  {
434  // swap two states (by swapping pointers)
435  size_t state1 = rand_index(m_size);
436  size_t state2;
437 
438  do
439  state2 = rand_index(m_size);
440  while (state2 == state1);
441 
442  for (size_t i = 0; i < InSize; ++i)
443  {
444  tranout_t temp = m_state_table[state1][i];
445  m_state_table[state1][i] = m_state_table[state2][i];
446  m_state_table[state2][i] = temp;
447  }
448 
449  break;
450  }
451  case MUTATE_INIT_STATE:
452  {
453  // change initial state
454  size_t choice;
455 
456  do
457  {
458  choice = rand_index(m_size);
459  }
460  while (m_init_state == choice);
461 
462  m_init_state = choice;
463 
464  break;
465  }
466  }
467  }
468  }
469 
470  // reset current state because init state may have changed
471  m_current_state = m_init_state;
472  }
473 
474  // Cause state transition
475  template <size_t InSize, size_t OutSize>
476  inline size_t simple_fsm<InSize,OutSize>::transition(size_t a_input)
477  {
478  // get output symbol for given input for current state
479  size_t output = m_state_table[m_current_state][a_input].m_output;
480 
481  // change to new state
482  m_current_state = m_state_table[m_current_state][a_input].m_new_state;
483 
484  // return output symbol
485  return output;
486  }
487 
488  // Reset to start-up state
489  template <size_t InSize, size_t OutSize>
491  {
492  m_current_state = m_init_state;
493  }
494 
495  // Get size
496  template <size_t InSize, size_t OutSize>
497  inline size_t simple_fsm<InSize,OutSize>::size() const
498  {
499  return m_size;
500  }
501 
502  // Get a copy of the internal table
503  template <size_t InSize, size_t OutSize>
504  inline const typename simple_fsm<InSize,OutSize>::tranout_t & simple_fsm<InSize,OutSize>::get_transition(size_t a_state, size_t a_input) const
505  {
506  return m_state_table[a_state][a_input];
507  }
508 
509  // Get number of input states
510  template <size_t InSize, size_t OutSize>
512  {
513  return InSize;
514  }
515 
516  // Get number of output states
517  template <size_t InSize, size_t OutSize>
519  {
520  return OutSize;
521  }
522 
523  // Get initial state
524  template <size_t InSize, size_t OutSize>
526  {
527  return m_init_state;
528  }
529 
530  // Get current state
531  template <size_t InSize, size_t OutSize>
533  {
534  return m_current_state;
535  }
536 };
537 
538 #endif
void reset()
Reset to start-up state.
Definition: simple_fsm.h:490
size_t m_init_state
Initial state.
Definition: simple_fsm.h:205
Wraps a roulette wheel for selecting mutations.
Definition: fsm_tools.h:77
static void set_mutation_weight(mutation_id a_type, double a_weight)
Set a mutation weight.
Definition: simple_fsm.h:362
tranout_t ** m_state_table
State table (the machine definition)
Definition: simple_fsm.h:202
size_t m_current_state
Current state.
Definition: simple_fsm.h:208
size_t num_output_states() const
Get number of output states.
Definition: simple_fsm.h:518
static size_t rand_index(size_t n)
Static function to allow use of g_random function pointer in random_shuffle.
Definition: evocommon.h:119
virtual ~simple_fsm()
Virtual destructor.
Definition: simple_fsm.h:337
simple_fsm & operator=(const simple_fsm< InSize, OutSize > &a_source)
Definition: simple_fsm.h:344
A set of common tools for finite state machines.
Definition: fsm_tools.h:47
simple_fsm(size_t a_size)
Creation constructor.
Definition: simple_fsm.h:254
size_t transition(size_t a_input)
Cause state transition.
Definition: simple_fsm.h:476
double get_real()
get the next value in the range [0,1)
Definition: evocommon.h:104
const tranout_t & get_transition(size_t a_state, size_t a_input) const
Get a transition from the internal state table.
Definition: simple_fsm.h:504
static mutation_selector g_selector
Global mutation selector.
Definition: simple_fsm.h:214
size_t m_output
The output value.
Definition: simple_fsm.h:70
static prng g_random
A shared random number generator.
Definition: evocommon.h:125
size_t m_size
Number of states.
Definition: simple_fsm.h:211
Defines a transition and output state pair.
Definition: simple_fsm.h:64
A finite state machine.
Definition: simple_fsm.h:60
size_t size() const
Get size.
Definition: simple_fsm.h:497
A toolkit and framework for implementing evolutionary algorithms.
Definition: evocommon.h:60
Elements shared by all classes in Evocosm.
Definition: evocommon.h:115
size_t num_input_states() const
Get number of input states.
Definition: simple_fsm.h:511
mutation_id
Types of mutation supported.
Definition: fsm_tools.h:51
size_t init_state() const
Get initial state.
Definition: simple_fsm.h:525
size_t m_new_state
The state to be transitioned to.
Definition: simple_fsm.h:67
size_t current_state() const
Get current state.
Definition: simple_fsm.h:532
void mutate(double a_rate)
Mutation.
Definition: simple_fsm.h:369

© 1996-2005 Scott Robert Ladd. All rights reserved.
HTML documentation generated by Dimitri van Heesch's excellent Doxygen tool.