def test_generate(self): self.assertEqual(len(population.generate()), 100) for inset_size in [10, 100]: for pop_size in [20, 200]: pop = population.generate(pop_size, inset_size) self.assertEqual(len(pop), pop_size) for inset in pop: self.assertEqual(len(inset), inset_size)
def run_simulation(population, speed=0.2, times=100): population.generate() strategies_statistics = [] for i in range(times * population.life_span): population.simulate_one_unit_of_time(speed) strategies_statistics.append(population.get_strategy_numbers()) strategy1_numbers = [numbers[0] for numbers in strategies_statistics] strategy2_numbers = [numbers[1] for numbers in strategies_statistics] plt.plot(strategy1_numbers, label=population.get_strategy_name(0)) plt.plot(strategy2_numbers, label=population.get_strategy_name(1)) plt.title("Changes in number of agents following the strategy.") plt.xlabel("Time") plt.ylabel("Number of agents") plt.legend() plt.show()
def run_simulation(population, speed=0.2, times=100): population.generate() strategies_statistics = [] for i in range(times*population.life_span): population.simulate_one_unit_of_time(speed) strategies_statistics.append(population.get_strategy_numbers()) strategy1_numbers = [numbers[0] for numbers in strategies_statistics] strategy2_numbers = [numbers[1] for numbers in strategies_statistics] plt.plot(strategy1_numbers, label=population.get_strategy_name(0)) plt.plot(strategy2_numbers, label=population.get_strategy_name(1)) plt.title("Changes in number of agents following the strategy.") plt.xlabel("Time") plt.ylabel("Number of agents") plt.legend() plt.show()
def test_evolve(self): level = [['.', '.', '.'], ['T', 'T', 'T']] original_population = population.generate() original_scores = population.score(original_population, level) new_population = population.evolve(original_population, original_scores) self.assertEqual(len(original_population), len(new_population)) for new_inset in new_population: self.assertEqual(len(new_inset), len(original_population[0]))
def test_evolve(self): level = [ ['.', '.', '.'], ['T', 'T', 'T'] ] original_population = population.generate() original_scores = population.score(original_population, level) new_population = population.evolve(original_population, original_scores) self.assertEqual(len(original_population), len(new_population)) for new_inset in new_population: self.assertEqual(len(new_inset), len(original_population[0]))
def generate_synthetic(n): print("Creating template households.") nhts_hh_templates = cache('template_households', lambda: [hhtmp for hhtmp in templates()], folder='nhts_templates') print("Generating sample population.") census_hhs = generate(n) print("Matching population households to template households.") synthetic_households = cache( str(n) + '_synthetic', lambda: merge_census_data(census_hhs, nhts_hh_templates), folder='synthetic_hh') print("Assigning activity locations.") # 4 people to a location avg (work, home, etc) assign_locations(synthetic_households, int(n / 4)) # assign_locations(synthetic_households) return synthetic_households
def main(): """ The main entry point. Runs the evolution and displays the progress and the results. """ help_string = 'A great adventure to find all treasures! Use the genetic algorithm to evolve' \ ' the best possible instruction set. A virtual machine interprets the instructions' \ ' and generates a path. A greedy guy in the generated level follows the path and' \ ' collects the treasures in the level.' url_string = 'https://github.com/chuckeles/genetic-treasures' # first, set up and parse command line options parser = ArgumentParser(description=help_string, epilog=url_string) parser.add_argument('-lw', '--width', type=int, default=8, help='level width (default: %(default)s)') parser.add_argument('-lh', '--height', type=int, default=8, help='level height (default: %(default)s)') parser.add_argument( '-tc', '--treasure-chance', type=int, default=10, help= 'chance that a treasure will be generated, in percents (default: %(default)s)' ) parser.add_argument( '-s', '--start', type=int, default=[0, 0], nargs=2, help= 'starting position of the guy collecting treasures (default: %(default)s)' ) parser.add_argument('-p', '--population', type=int, default=100, help='population size (default: %(default)s)') parser.add_argument( '-is', '--instruction-size', type=int, default=64, help='size of the instruction set (default: %(default)s)') parser.add_argument( '-n', '--number-of-generations', type=int, default=200, help= 'number of generations to run the evolution for (default: %(default)s)' ) parser.add_argument( '-pp', '--print-progress', type=int, default=10, help='print progress every N generations (default: %(default)s)') parser.add_argument( '-mi', '--machine-iterations', type=int, default=500, help= 'maximum number of iterations the virtual machine can make (default: %(default)s)' ) parser.add_argument( '-mc', '--mutation-chance', type=int, default=5, help='mutation chance for new instruction sets (default: %(default)s)') parser.add_argument( '-cr', '--crossover-random', action='store_true', help= 'if specified, the crossover takes each byte randomly from either parent,' ' instead of taking continuous parts from both parents (default: %(default)s)' ) parser.add_argument( '-mf', '--mutation-function', choices=['bit', 'byte', 'both'], default='bit', help= 'mutation function to use - either mutate just bits or the whole bytes' ' (choices: %(choices)s) (default: %(default)s)') parser.add_argument('-sf', '--selection-function', choices=['roulette', 'tournament'], default='roulette', help='selection function to use' ' (choices: %(choices)s) (default: %(default)s)') args = parser.parse_args() # generate a level print('Generating a level of size', colored('%d×%d' % (args.width, args.height), 'blue'), 'with treasure chance', colored(args.treasure_chance, 'yellow')) generated_level = level.generate(args.width, args.height, args.treasure_chance) level.print_level(generated_level, args.start) # count the number of treasures number_of_treasures = sum(generated_level, []).count('T') print('There are', colored(number_of_treasures, 'yellow'), 'treasures in total') print() # generate a population print('Generating the initial population of', colored(args.population, 'blue'), 'instruction sets with size', colored(args.instruction_size, 'blue')) print() current_population = population.generate(args.population, args.instruction_size) current_scores = population.score( current_population, generated_level, start=args.start, max_machine_iterations=args.machine_iterations) generation = 0 best_inset = current_population[0] best_score = 0 # lookup for mutation function mf = { 'bit': instruction_set.mutate_bits, 'bytes': instruction_set.mutate_bytes, 'both': instruction_set.mutate_combined } # repeat until all treasures are found or the user stops while True: # run the evolution try: print('Running the evolution for', colored(args.number_of_generations, 'blue'), 'generations') for iteration in range(args.number_of_generations): # evolve and score a new population current_population = population \ .evolve(current_population, current_scores, mutation_chance=args.mutation_chance, crossover_take_random=args.crossover_random, mutation_function=mf[args.mutation_function], parent_selection=population.select_parent_roulette if args.selection_function == 'roulette' else population.select_parent_tournament) current_scores = population.score( current_population, generated_level, start=args.start, max_machine_iterations=args.machine_iterations) # increase generation number generation += 1 # print progress if iteration % args.print_progress == 0: avg_fitness = sum(current_scores) / len(current_scores) print('\b' * 256, end='') print('Generation number', colored(generation, 'blue'), 'has average fitness', fitness_color(avg_fitness, number_of_treasures), 'and the best fitness is', fitness_color(max(current_scores), number_of_treasures), end='') print(' ' * 16, end='') sys.stdout.flush() # find the best path for i, inset in enumerate(current_population): if current_scores[i] > best_score: best_score = current_scores[i] best_inset = inset print() print(colored('Finished', 'green'), 'the evolution') # allow the user to stop the evolution except KeyboardInterrupt: print() print(colored('Stopping', 'red'), 'the evolution') print() best_path = machine.interpret(best_inset, max_iterations=args.machine_iterations) collected_treasures, steps_taken = level.run_path(generated_level, best_path, start=args.start) collected_percent = round( collected_treasures / number_of_treasures * 100, 2) # print the path, the fitness, and the treasures taken print('The best instruction set has fitness', fitness_color(best_score, number_of_treasures)) print('The generated path is:', colored(format_path(best_path[:steps_taken]), 'cyan')) print('The guy collected', colored(collected_treasures, 'yellow'), 'treasures', '(' + percent_color(collected_percent) + '%)') # check if all treasures are collected if collected_treasures == number_of_treasures: break else: # offer to continue or stop evolving try: print() answer = input( 'The best path does not yet collect all treasures, do you want to keep running?' ' [' + colored('y', 'green') + '/' + colored('N', 'red') + '] ') print() if answer != 'y' and answer != 'Y': break # interrupt can also be used as a no except KeyboardInterrupt: print() break # finally, print the level with the path level.print_level_path(generated_level, best_path, args.start)