nodes: 0, module; 1, function_definition; 2, function_name:iterate; 3, parameters; 4, block; 5, identifier:MachineClass; 6, default_parameter; 7, default_parameter; 8, default_parameter; 9, default_parameter; 10, default_parameter; 11, expression_statement; 12, function_definition; 13, function_definition; 14, function_definition; 15, expression_statement; 16, expression_statement; 17, if_statement; 18, try_statement; 19, return_statement; 20, identifier:stop_function; 21, lambda; 22, identifier:machines; 23, integer:1000; 24, identifier:survival_rate; 25, float:0.05; 26, identifier:mutation_rate; 27, float:0.075; 28, identifier:silent; 29, False; 30, comment:"""Creates a bunch of machines, runs them for a number of steps and then
      gives them a fitness score.  The best produce offspring that are passed on
      to the next generation.
  
      Args:
          setup: Function taking a Machine argument, makes the machine ready
          machine_class: A class that should inherit from Machine and contain the
          following methods:
              setUp(self) [optional]: Run before each new run, should at least
              call self.reset() for each run.
  
              tearDown(self) [optional]: Run after each run.
  
              crossover(self, other): Returns a Machine offspring between itself and
              another Machine.
  
              score(self):  Score the machine. Lower is better. Can return a
              tuple of values used to sort the machines from best to worst in
              fitness.
  
          stop_function: An optional function that takes the current generation
          number and returns True if the processing should stop.
  
          machines: The number of machines to create for each generation.
  
          steps: The number of instructions each machine is allowed to execute in
          each run.
  
          code_length: Tuple of (minimum code length, maximum code length) for a
          Machine.
  
          survival_ratio: Ratio of the best Machines which are allowed to produce
          offspring for the next generation.
  
          mutation_rate: Rate for each machine's chance of being mutated.
      """; 31, function_name:make_random; 32, parameters; 33, block; 34, function_name:run_once; 35, parameters; 36, block; 37, function_name:make_offspring; 38, parameters; 39, block; 40, assignment; 41, assignment; 42, identifier:silent; 43, block; 44, else_clause; 45, block; 46, except_clause; 47, identifier:survivors; 48, lambda_parameters; 49, comparison_operator:iterations < 10000; 50, identifier:n; 51, return_statement; 52, identifier:m; 53, expression_statement; 54, expression_statement; 55, expression_statement; 56, return_statement; 57, identifier:survivors; 58, expression_statement; 59, expression_statement; 60, return_statement; 61, identifier:generation; 62, call; 63, identifier:survivors; 64, identifier:generation; 65, expression_statement; 66, block; 67, expression_statement; 68, while_statement; 69, identifier:KeyboardInterrupt; 70, block; 71, identifier:iterations; 72, identifier:iterations; 73, integer:10000; 74, call; 75, call; 76, call; 77, call; 78, identifier:m; 79, assignment; 80, assignment; 81, call; 82, identifier:map; 83, argument_list; 84, assignment; 85, expression_statement; 86, assignment; 87, not_operator; 88, block; 89, pass_statement; 90, attribute; 91, argument_list; 92, attribute; 93, argument_list; 94, attribute; 95, argument_list; 96, attribute; 97, argument_list; 98, identifier:a; 99, call; 100, identifier:b; 101, call; 102, attribute; 103, argument_list; 104, identifier:make_random; 105, call; 106, identifier:log; 107, lambda; 108, assignment; 109, identifier:iterations; 110, integer:0; 111, call; 112, expression_statement; 113, expression_statement; 114, comment:# Run all machines in this generation; 115, expression_statement; 116, comment:# Sort machines from best to worst; 117, expression_statement; 118, comment:# Select the best; 119, expression_statement; 120, comment:# Remove code larger than 50; 121, for_statement; 122, comment:# Remove dead ones; 123, expression_statement; 124, comment:#survivors = [s for s in survivors if len(s.code)<=50]; 125, comment:# All dead? start with a new set; 126, if_statement; 127, comment:# Create a new generation based on the survivors.; 128, expression_statement; 129, expression_statement; 130, expression_statement; 131, comment:# Add mutations from time to time; 132, for_statement; 133, expression_statement; 134, call; 135, identifier:randomize; 136, identifier:m; 137, identifier:setUp; 138, identifier:m; 139, identifier:run; 140, identifier:m; 141, identifier:tearDown; 142, identifier:stochastic_choice; 143, argument_list; 144, identifier:stochastic_choice; 145, argument_list; 146, identifier:a; 147, identifier:crossover; 148, identifier:b; 149, identifier:xrange; 150, argument_list; 151, lambda_parameters; 152, None; 153, identifier:log; 154, identifier:_log; 155, identifier:stop_function; 156, argument_list; 157, augmented_assignment; 158, call; 159, assignment; 160, assignment; 161, assignment; 162, identifier:s; 163, identifier:survivors; 164, block; 165, assignment; 166, comparison_operator:len(survivors) == 0; 167, block; 168, call; 169, assignment; 170, assignment; 171, identifier:m; 172, identifier:generation; 173, block; 174, call; 175, identifier:MachineClass; 176, argument_list; 177, identifier:survivors; 178, identifier:survivors; 179, identifier:machines; 180, identifier:s; 181, default_parameter; 182, identifier:iterations; 183, identifier:survivors; 184, identifier:iterations; 185, integer:1; 186, identifier:log; 187, argument_list; 188, identifier:generation; 189, call; 190, identifier:generation; 191, call; 192, identifier:survivors; 193, subscript; 194, if_statement; 195, identifier:survivors; 196, list_comprehension; 197, call; 198, integer:0; 199, expression_statement; 200, expression_statement; 201, expression_statement; 202, continue_statement; 203, identifier:log; 204, argument_list; 205, identifier:cross; 206, lambda; 207, identifier:generation; 208, call; 209, if_statement; 210, identifier:log; 211, argument_list; 212, identifier:stream; 213, None; 214, string:"running ... "; 215, identifier:map; 216, argument_list; 217, identifier:sorted; 218, argument_list; 219, identifier:generation; 220, slice; 221, comparison_operator:len(s.code) >= 50; 222, block; 223, identifier:s; 224, for_in_clause; 225, if_clause; 226, identifier:len; 227, argument_list; 228, call; 229, assignment; 230, assignment; 231, string:"crossover ... "; 232, lambda_parameters; 233, call; 234, identifier:map; 235, argument_list; 236, comparison_operator:random.random() > mutation_rate; 237, block; 238, binary_operator:"\rgen %d 1-fitness %.12f avg code len %.2f avg stack len %.2f\n" %
                  (iterations,
                   average(survivors, lambda m: m.score()),
                   average(survivors, lambda m: len(m.code)),
                   average(survivors, lambda m: len(m.stack) + len(m.return_stack))); 239, identifier:run_once; 240, identifier:generation; 241, identifier:generation; 242, keyword_argument; 243, call; 244, call; 245, integer:50; 246, expression_statement; 247, identifier:s; 248, identifier:survivors; 249, comparison_operator:len(s.code)>0; 250, identifier:survivors; 251, identifier:log; 252, argument_list; 253, identifier:survivors; 254, call; 255, identifier:generation; 256, identifier:survivors; 257, identifier:_; 258, identifier:make_offspring; 259, argument_list; 260, identifier:cross; 261, call; 262, call; 263, identifier:mutation_rate; 264, expression_statement; 265, string:"\rgen %d 1-fitness %.12f avg code len %.2f avg stack len %.2f\n"; 266, tuple; 267, identifier:key; 268, lambda; 269, identifier:int; 270, argument_list; 271, identifier:len; 272, argument_list; 273, assignment; 274, call; 275, integer:0; 276, string:"\nNo survivors, restarting"; 277, identifier:map; 278, argument_list; 279, identifier:survivors; 280, identifier:xrange; 281, argument_list; 282, attribute; 283, argument_list; 284, call; 285, identifier:iterations; 286, call; 287, call; 288, call; 289, lambda_parameters; 290, call; 291, binary_operator:survival_rate * len(generation); 292, attribute; 293, attribute; 294, subscript; 295, identifier:len; 296, argument_list; 297, identifier:make_random; 298, call; 299, identifier:machines; 300, identifier:random; 301, identifier:random; 302, attribute; 303, argument_list; 304, identifier:average; 305, argument_list; 306, identifier:average; 307, argument_list; 308, identifier:average; 309, argument_list; 310, identifier:m; 311, attribute; 312, argument_list; 313, identifier:survival_rate; 314, call; 315, identifier:s; 316, identifier:code; 317, identifier:s; 318, identifier:code; 319, attribute; 320, slice; 321, attribute; 322, identifier:xrange; 323, argument_list; 324, identifier:m; 325, identifier:mutate; 326, identifier:survivors; 327, lambda; 328, identifier:survivors; 329, lambda; 330, identifier:survivors; 331, lambda; 332, identifier:m; 333, identifier:score; 334, identifier:len; 335, argument_list; 336, identifier:s; 337, identifier:code; 338, integer:50; 339, identifier:s; 340, identifier:code; 341, identifier:machines; 342, lambda_parameters; 343, call; 344, lambda_parameters; 345, call; 346, lambda_parameters; 347, binary_operator:len(m.stack) + len(m.return_stack); 348, identifier:generation; 349, identifier:m; 350, attribute; 351, argument_list; 352, identifier:m; 353, identifier:len; 354, argument_list; 355, identifier:m; 356, call; 357, call; 358, identifier:m; 359, identifier:score; 360, attribute; 361, identifier:len; 362, argument_list; 363, identifier:len; 364, argument_list; 365, identifier:m; 366, identifier:code; 367, attribute; 368, attribute; 369, identifier:m; 370, identifier:stack; 371, identifier:m; 372, identifier:return_stack
code: def iterate(MachineClass, stop_function=lambda iterations: iterations < 10000,
          machines=1000, survival_rate=0.05, mutation_rate=0.075, silent=False):
      """Creates a bunch of machines, runs them for a number of steps and then
      gives them a fitness score.  The best produce offspring that are passed on
      to the next generation.
  
      Args:
          setup: Function taking a Machine argument, makes the machine ready
          machine_class: A class that should inherit from Machine and contain the
          following methods:
              setUp(self) [optional]: Run before each new run, should at least
              call self.reset() for each run.
  
              tearDown(self) [optional]: Run after each run.
  
              crossover(self, other): Returns a Machine offspring between itself and
              another Machine.
  
              score(self):  Score the machine. Lower is better. Can return a
              tuple of values used to sort the machines from best to worst in
              fitness.
  
          stop_function: An optional function that takes the current generation
          number and returns True if the processing should stop.
  
          machines: The number of machines to create for each generation.
  
          steps: The number of instructions each machine is allowed to execute in
          each run.
  
          code_length: Tuple of (minimum code length, maximum code length) for a
          Machine.
  
          survival_ratio: Ratio of the best Machines which are allowed to produce
          offspring for the next generation.
  
          mutation_rate: Rate for each machine's chance of being mutated.
      """
      def make_random(n):
          return MachineClass().randomize()
  
      def run_once(m):
          m.setUp()
          m.run()
          m.tearDown()
          return m
  
      def make_offspring(survivors):
          a = stochastic_choice(survivors)
          b = stochastic_choice(survivors)
          return a.crossover(b)
  
      generation = map(make_random, xrange(machines))
      survivors = generation
  
      if silent:
          log = lambda s,stream=None: None
      else:
          log = _log
  
      try:
          iterations = 0
          while not stop_function(iterations, survivors):
              iterations += 1
              log("running ... ")
  
              # Run all machines in this generation
              generation = map(run_once, generation)
  
              # Sort machines from best to worst
              generation = sorted(generation, key=lambda m: m.score())
  
              # Select the best
              survivors = generation[:int(survival_rate * len(generation))]
  
              # Remove code larger than 50
              for s in survivors:
                  if len(s.code) >= 50:
                      s.code = s.code[:50]
  
              # Remove dead ones
              survivors = [s for s in survivors if len(s.code)>0]
  
              #survivors = [s for s in survivors if len(s.code)<=50]
              # All dead? start with a new set
              if len(survivors) == 0:
                  log("\nNo survivors, restarting")
                  survivors = map(make_random, xrange(machines))
                  generation = survivors
                  continue
  
              # Create a new generation based on the survivors.
              log("crossover ... ")
              cross = lambda _: make_offspring(survivors)
              generation = map(cross, xrange(machines))
  
              # Add mutations from time to time
              for m in generation:
                  if random.random() > mutation_rate:
                      m.mutate()
  
              log("\rgen %d 1-fitness %.12f avg code len %.2f avg stack len %.2f\n" %
                  (iterations,
                   average(survivors, lambda m: m.score()),
                   average(survivors, lambda m: len(m.code)),
                   average(survivors, lambda m: len(m.stack) + len(m.return_stack))))
      except KeyboardInterrupt:
          pass
  
      return survivors