Skip to content

Commit 8453845

Browse files
drvinceknightmarcharper
authored andcommitted
Adding ability to start have starting population.
1 parent c70256e commit 8453845

File tree

3 files changed

+53
-26
lines changed

3 files changed

+53
-26
lines changed

analyze_data.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
from operator import itemgetter
22
import sys
33

4-
if __name__ == "__main__":
5-
data_filename = sys.argv[1]
4+
def read_top_tables(filename, n):
5+
"""Read in the n top performing results from a given file"""
66
results = []
7-
with open(data_filename) as data:
7+
with open(filename) as data:
88
for line in data:
99
results.append(line.split(','))
1010
results.sort(reverse=True, key=itemgetter(2))
11-
for result in results[:10]:
11+
return results[:n]
12+
13+
if __name__ == "__main__":
14+
data_filename = sys.argv[1]
15+
results = read_top_tables(data_filename, 10)
16+
for result in results:
1217
print(result[2], result[1])

axelrod_utils.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ def score_single(me, other, iterations=200):
144144
def score_for(my_strategy_factory, iterations=200):
145145
"""
146146
Given a function that will return a strategy, calculate the average score per turn
147-
against all ordinary strategies. If the opponent is classified as stochastic, then
148-
run 100 repetitions and take the average to get a good estimate.
147+
against all ordinary strategies. If the opponent is classified as stochastic, then
148+
run 100 repetitions and take the average to get a good estimate.
149149
"""
150150
scores_for_all_opponents = []
151151
for opponent in get_strategies():
@@ -157,9 +157,9 @@ def score_for(my_strategy_factory, iterations=200):
157157
for _ in range(repetitions):
158158
me = my_strategy_factory()
159159
other = opponent()
160-
# make sure that both players know what length the match will be
161-
me.set_tournament_attributes(length=iterations)
162-
other.set_tournament_attributes(length=iterations)
160+
# make sure that both players know what length the match will be
161+
me.set_match_attributes(length=iterations)
162+
other.set_match_attributes(length=iterations)
163163
scores_for_this_opponent.append(score_single(me, other, iterations))
164164

165165
average_score_vs_opponent = sum(scores_for_this_opponent) / len(scores_for_this_opponent)
@@ -172,6 +172,10 @@ def id_for_table(table):
172172
"""Return a string representing the values of a lookup table dict"""
173173
return ''.join([v for k, v in sorted(table.items())])
174174

175+
def table_from_id(string_id, keys):
176+
"""Return a lookup table dict from a string representing the values"""
177+
return dict(zip(keys, string_id))
178+
175179
def do_table(table):
176180
"""
177181
Take a lookup table dict, construct a lambda factory for it, and return
@@ -192,5 +196,3 @@ def score_tables(tables, pool):
192196
if not isinstance(x[0], float):
193197
print(x)
194198
return list(results)
195-
196-

lookup_evolve.py

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
"""Lookup Evolve.
22
33
Usage:
4-
lookup_evolve.py [-h] [-p PLIES] [-s STARTING_PLIES] [-g GENERATIONS] [-k STARTING_POPULATION] [-u MUTATION_RATE] [-b BOTTLENECK] [-i PROCESSORS] [-o OUTPUT_FILE]
4+
lookup_evolve.py [-h] [-p PLIES] [-s STARTING_PLIES] [-g GENERATIONS] [-k
5+
STARTING_POPULATION] [-u MUTATION_RATE] [-b BOTTLENECK] [-i PROCESSORS] [-o
6+
OUTPUT_FILE] [-z INITIAL_POPULATION_FILE]
57
68
Options:
7-
-h --help show this
8-
-p PLIES specify the number of recent plays in the lookup table [default: 2]
9-
-s STARTING_PLIES specify the number of opponent starting plays in the lookup table [default: 2]
10-
-g GENERATIONS how many generations to run the program for [default: 100]
11-
-k STARTING_POPULATION starting population for the simulation [default: 5]
12-
-u MUTATION_RATE mutation rate i.e. probability that a given value will flip [default: 0.1]
13-
-b BOTTLENECK number of individuals to keep from each generation [default: 10]
14-
-i PROCESSORS number of processors to use [default: 1]
15-
-o OUTPUT_FILE file to write statistics to [default: evolve.csv]
9+
-h --help show this
10+
-p PLIES specify the number of recent plays in the lookup table [default: 2]
11+
-s STARTING_PLIES specify the number of opponent starting plays in the lookup table [default: 2]
12+
-g GENERATIONS how many generations to run the program for [default: 100]
13+
-k STARTING_POPULATION starting population size for the simulation [default: 5]
14+
-u MUTATION_RATE mutation rate i.e. probability that a given value will flip [default: 0.1]
15+
-b BOTTLENECK number of individuals to keep from each generation [default: 10]
16+
-i PROCESSORS number of processors to use [default: 1]
17+
-o OUTPUT_FILE file to write statistics to [default: evolve.csv]
18+
-z INITIAL_POPULATION_FILE file to read an initial population from [default: None]
19+
1620
1721
1822
"""
@@ -25,6 +29,7 @@
2529
from docopt import docopt
2630

2731
import axelrod_utils
32+
import analyze_data
2833

2934

3035
"""
@@ -57,7 +62,7 @@ def evolve(starting_tables, mutation_rate, generations, bottleneck, pool, plys,
5762
"""
5863
The function that does everything. Take a set of starting tables, and in each generation:
5964
- add a bunch more random tables
60-
- simulate recombination between each pair of tables
65+
- simulate recombination between each pair of tables
6166
- randomly mutate the current population of tables
6267
- calculate the fitness function i.e. the average score per turn
6368
- keep the best individuals and discard the rest
@@ -117,7 +122,7 @@ def evolve(starting_tables, mutation_rate, generations, bottleneck, pool, plys,
117122
return (current_bests)
118123

119124
def table_keys(plys, opponent_start_plys):
120-
"""Return randomly-generated lookup tables"""
125+
"""Return key for given size of table"""
121126

122127
# generate all the possible recent histories for the player and opponent
123128
player_histories = [''.join(x) for x in itertools.product('CD', repeat=plys)]
@@ -148,8 +153,8 @@ def get_random_tables(plys, opponent_start_plys, number):
148153

149154
if __name__ == '__main__':
150155
arguments = docopt(__doc__, version='Lookup Evolver 0.1')
151-
# set up the process pool
152-
pool = Pool(processes=int(arguments['-i']))
156+
# set up the process pool
157+
pool = Pool(processes=int(arguments['-i']))
153158

154159
# vars for the genetic algorithm
155160
starting_pop = int(arguments['-k'])
@@ -158,10 +163,25 @@ def get_random_tables(plys, opponent_start_plys, number):
158163
bottleneck = int(arguments['-b'])
159164
plys = int(arguments['-p'])
160165
start_plys = int(arguments['-s'])
166+
initial_population = arguments['-z']
161167

162168
# generate a starting population of tables and score them
163169
# these will start off the first generation
164-
starting_tables = get_random_tables(plys, start_plys, starting_pop)
170+
if initial_population == 'None':
171+
starting_tables = get_random_tables(plys, start_plys, starting_pop)
172+
else:
173+
keys = table_keys(plys, start_plys)
174+
data = analyze_data.read_top_tables(initial_population, starting_pop)
175+
starting_tables = []
176+
for row in data:
177+
starting_tables.append(axelrod_utils.table_from_id(row[1], keys))
178+
# If insufficient size in data augment with random tables:
179+
if len(starting_tables) < starting_pop:
180+
needed_num = starting_pop - len(starting_tables)
181+
starting_tables = starting_tables + get_random_tables(plys,
182+
start_plys,
183+
needed_num)
184+
165185
real_starting_tables = axelrod_utils.score_tables(starting_tables, pool)
166186

167187
# kick off the evolve function

0 commit comments

Comments
 (0)