Ejemplo n.º 1
0
def evolve(starting_tables, mutation_rate, generations, bottleneck, pool, plys, start_plys, starting_pop, output_file):
    """
    The function that does everything. Take a set of starting tables, and in each generation:
    - add a bunch more random tables
    - simulate recombination between each pair of tables 
    - randomly mutate the current population of tables
    - calculate the fitness function i.e. the average score per turn
    - keep the best individuals and discard the rest
    - write out summary statistics to the output file

    """

    # current_bests is a list of 2-tuples, each of which consists of a score and a lookup table
    # initially the collection of best tables are the ones supplied to start with
    current_bests = starting_tables

    keys = list(sorted(table_keys(plys, start_plys)))

    for generation in range(generations):

        # because this is a long-running process we'll just keep appending to the output file
        # so we can monitor it while it's running
        with open(output_file, "a") as output:
            print("doing generation " + str(generation))

            # the tables at the start of this generation are the best ones from the
            # previous generation (i.e. the second element of each tuple) plus a bunch
            # of random ones
            tables_to_copy = [x[1] for x in current_bests] + get_random_tables(plys, start_plys, starting_pop)

            # set up new list to hold the tables that we are going to want to score
            copies = crossover(tables_to_copy, mutation_rate, keys=keys)

            # Mutations
            for c in copies:
                # flip each value with a probability proportional to the mutation rate
                for history, move in c.items():
                    if random.random() < mutation_rate:
                        c[history] = 'C' if move == 'D' else 'D'

            # the population of tables we want to consider includes the recombined, mutated copies, plus the originals
            population = copies + tables_to_copy

            # map the population to get a list of (score, table) tuples
            # this list will be sorted by score, best tables first
            results = axelrod_utils.score_tables(population, pool)

            # keep the user informed
            print("generation " + str(generation))

            # the best tables from this generation become the starting tables for the next generation
            current_bests = results[0: bottleneck]

            # get all the scores for this generation
            scores = [score for score, table in results]

            # write the generation number, identifier of current best table, score of current best table, mean score, and SD of scores to the output file
            for value in [generation, axelrod_utils.id_for_table(results[0][1]), results[0][0], axelrod_utils.mean(scores), axelrod_utils.pstdev(scores)]:
                output.write(str(value) + ",")
            output.write("\n")

    return (current_bests)
Ejemplo n.º 2
0
def evolve(starting_tables, mutation_rate, generations, bottleneck, pool, plys,
           start_plys, starting_pop, output_file):
    """
    The function that does everything. Take a set of starting tables, and in each generation:
    - add a bunch more random tables
    - simulate recombination between each pair of tables 
    - randomly mutate the current population of tables
    - calculate the fitness function i.e. the average score per turn
    - keep the best individuals and discard the rest
    - write out summary statistics to the output file

    """

    # current_bests is a list of 2-tuples, each of which consists of a score and a lookup table
    # initially the collection of best tables are the ones supplied to start with
    current_bests = starting_tables

    for generation in range(generations):

        # because this is a long-running process we'll just keep appending to the output file
        # so we can monitor it while it's running
        with open(output_file, "a") as output:
            print("doing generation " + str(generation))

            # the tables at the start of this generation are the best ones from the
            # previous generation (i.e. the second element of each tuple) plus a bunch
            # of random ones
            tables_to_copy = [x[1] for x in current_bests] + get_random_tables(
                plys, start_plys, starting_pop)

            # set up new list to hold the tables that we are going to want to score
            copies = []

            # each table reproduces with each other table to produce one offspring
            for t1 in tables_to_copy:
                for t2 in tables_to_copy:

                    # for reproduction, pick a random crossover point
                    crossover = random.randrange(len(t1.items()))

                    # the values (plays) for the offspring are copied from t1 up to the crossover point,
                    # and from t2 from the crossover point to the end
                    new_values = copy.deepcopy(
                        t1.values()[0:crossover]) + copy.deepcopy(
                            t2.values()[crossover:])

                    # turn those new values into a valid lookup table by copying the keys from t1 (the keys are the same for
                    # all tables, so it doesn't matter which one we pick)
                    new_table = dict(zip(copy.deepcopy(t1.keys()), new_values))
                    copies.append(new_table)

            # now copies contains a list of the new offspring tables, do mutation
            for c in copies:
                # flip each value with a probability proportional to the mutation rate
                for history, move in c.items():
                    if random.random() < mutation_rate:
                        c[history] = 'C' if move == 'D' else 'D'

            # the population of tables we want to consider includes the recombined, mutated copies, plus the originals
            population = copies + tables_to_copy

            # map the population to get a list of (score, table) tuples
            # this list will be sorted by score, best tables first
            results = axelrod_utils.score_tables(population, pool)

            # keep the user informed
            print("generation " + str(generation))

            # the best tables from this generation become the starting tables for the next generation
            current_bests = results[0:bottleneck]

            # get all the scores for this generation
            scores = [score for score, table in results]

            # write the generation number, identifier of current best table, score of current best table, mean score, and SD of scores to the output file
            for value in [
                    generation,
                    axelrod_utils.id_for_table(results[0][1]), results[0][0],
                    axelrod_utils.mean(scores),
                    axelrod_utils.pstdev(scores)
            ]:
                output.write(str(value) + ",")
            output.write("\n")

    return (current_bests)
Ejemplo n.º 3
0
    lookup_table_keys = table_keys(plys, opponent_start_plys)

    # to get a pattern, we just randomly pick between C and D for each key
    patterns = [''.join([random.choice("CD") for _ in lookup_table_keys]) for i in range(number)]

    # zip together the keys and the patterns to give a table
    tables = [dict(zip(lookup_table_keys, pattern)) for pattern in patterns]

    return tables

if __name__ == '__main__':
    arguments = docopt(__doc__, version='Lookup Evolver 0.1')
    # set up the process pool 
    pool = Pool(processes=int(arguments['-i'])) 

    # vars for the genetic algorithm
    starting_pop = int(arguments['-k'])
    mutation_rate = float(arguments['-u'])
    generations = int(arguments['-g'])
    bottleneck = int(arguments['-b'])
    plys = int(arguments['-p'])
    start_plys = int(arguments['-s'])

    # generate a starting population of tables and score them
    # these will start off the first generation
    starting_tables = get_random_tables(plys, start_plys, starting_pop)
    real_starting_tables = axelrod_utils.score_tables(starting_tables, pool)

    # kick off the evolve function
    evolve(real_starting_tables, mutation_rate, generations, bottleneck, pool, plys, start_plys, starting_pop, arguments['-o'])
Ejemplo n.º 4
0
    ]

    # zip together the keys and the patterns to give a table
    tables = [dict(zip(lookup_table_keys, pattern)) for pattern in patterns]

    return tables


if __name__ == '__main__':
    arguments = docopt(__doc__, version='Lookup Evolver 0.1')

    # set up the process pool
    pool = Pool(processes=int(arguments['-i']))

    # vars for the genetic algorithm
    starting_pop = int(arguments['-k'])
    mutation_rate = float(arguments['-u'])
    generations = int(arguments['-g'])
    bottleneck = int(arguments['-b'])
    plys = int(arguments['-p'])
    start_plys = int(arguments['-s'])

    # generate a starting population of tables and score them
    # these will start off the first generation
    starting_tables = get_random_tables(plys, start_plys, starting_pop)
    real_starting_tables = axelrod_utils.score_tables(starting_tables, pool)

    # kick off the evolve function
    evolve(real_starting_tables, mutation_rate, generations, bottleneck, pool,
           plys, start_plys, starting_pop, arguments['-o'])