Skip to content

Commit 4b42987

Browse files
committed
Various fixes, better loading of params from files, first tests
1 parent f111d14 commit 4b42987

File tree

9 files changed

+89
-64
lines changed

9 files changed

+89
-64
lines changed

analyze_data.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
1-
from operator import itemgetter
1+
import csv
22
import sys
33

4-
def read_top_tables(filename, n):
4+
def read_data(filename):
55
"""Read in the n top performing results from a given file"""
66
results = []
7-
with open(filename) as data:
8-
for line in data:
9-
results.append(line.split(','))
10-
117
with open(filename) as data:
128
reader = csv.reader(data)
139
for line in reader:
14-
results.append((float(line[3]), int(line[0]), line[-1]))
15-
results.sort(reverse=True, key=itemgetter(0))
16-
return results[:n]
10+
results.append((float(line[-2]), line[-1]))
11+
return results
1712

1813
if __name__ == "__main__":
1914
data_filename = sys.argv[1]
20-
results = read_top_tables(data_filename, 10)
21-
for result in results:
22-
print(result[0], result[-1])
15+
results = read_data(data_filename)
16+
results.sort()
17+
for result in results[-10:]:
18+
print(result[0], result[1])

analyze_weights.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

ann_evolve.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
Options:
1616
-h --help Show help
1717
--generations GENERATIONS Generations to run the EA [default: 500]
18-
--population POPULATION Starting population size [default: 10]
18+
--population POPULATION Starting population size [default: 40]
1919
--mu MUTATION_RATE Mutation rate [default: 0.1]
20-
--bottleneck BOTTLENECK Number of individuals to keep from each generation [default: 5]
20+
--bottleneck BOTTLENECK Number of individuals to keep from each generation [default: 10]
2121
--processes PROCESSES Number of processes to use [default: 1]
22-
--output OUTPUT_FILE File to write data to [default: ann_weights.csv]
22+
--output OUTPUT_FILE File to write data to [default: ann_params.csv]
2323
--objective OBJECTIVE Objective function [default: score]
2424
--repetitions REPETITIONS Repetitions in objective [default: 100]
2525
--turns TURNS Turns in each match [default: 200]
@@ -96,7 +96,7 @@ def mutate_weights(weights, num_features, num_hidden, mutation_rate,
9696
for i, r in enumerate(randoms):
9797
if r < mutation_rate:
9898
p = 1 + random.uniform(-1, 1) * mutation_distance
99-
weights[i] = weights[i] * p
99+
weights[i] *= p
100100
return weights
101101

102102
def mutate(self):
@@ -128,8 +128,8 @@ def __repr__(self):
128128
@classmethod
129129
def parse_repr(cls, s):
130130
elements = list(map(float, s.split(':')))
131-
num_features = elements[0]
132-
num_hidden = elements[1]
131+
num_features = int(elements[0])
132+
num_hidden = int(elements[1])
133133
weights = elements[2:]
134134
return cls(num_features, num_hidden, weights)
135135

evolve_utils.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def __init__(self, params_class, params_args, size, objective, output_filename,
145145
self.params_class = params_class
146146
self.bottleneck = bottleneck
147147
self.pool = Pool(processes=processes)
148-
self.outputer = Outputer(output_filename)
148+
self.outputer = Outputer(output_filename, mode='a')
149149
self.size = size
150150
self.objective = objective
151151
if not bottleneck:
@@ -204,12 +204,16 @@ def evolve(self):
204204
## Next Population
205205
indices_to_keep = [p for (s, p) in results[0: self.bottleneck]]
206206
self.subset_population(indices_to_keep)
207-
# Add variants
207+
# Add mutants of the best players
208+
best_mutants = [p.copy() for p in self.population]
209+
for p in best_mutants:
210+
p.mutate()
211+
self.population.append(p)
212+
# Add random variants
208213
random_params = [self.params_class(*self.params_args)
209214
for _ in range(self.bottleneck // 2)]
210215
params_to_modify = [params.copy() for params in self.population]
211216
params_to_modify += random_params
212-
213217
# Crossover
214218
size_left = self.size - len(params_to_modify)
215219
params_to_modify = self.crossover(params_to_modify, size_left)
@@ -230,6 +234,23 @@ def run(self, generations):
230234
pass
231235

232236

237+
def load_params(params_class, filename, num):
238+
"""Load the best num parameters from the given file."""
239+
parser = params_class.parse_repr
240+
all_params = []
241+
242+
with open(filename) as datafile:
243+
reader = csv.reader(datafile)
244+
for line in reader:
245+
score, rep = float(line[-2]), line[-1]
246+
all_params.append((score, rep))
247+
all_params.sort(reverse=True)
248+
best_params = []
249+
for score, rep in all_params[:num]:
250+
best_params.append(parser(rep))
251+
return best_params
252+
253+
233254
## This function is only used for PSO.
234255

235256
def score_for(strategy_factory, objective, args=None, opponents=None):

fsm_evolve.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
--mu MUTATION_RATE Mutation rate [default: 0.1]
1616
--bottleneck BOTTLENECK Number of individuals to keep from each generation [default: 10]
1717
--processes PROCESSES Number of processes to use [default: 1]
18-
--output OUTPUT_FILE File to write data to [default: fsm_tables.csv]
18+
--output OUTPUT_FILE File to write data to [default: fsm_params.csv]
1919
--objective OBJECTIVE Objective function [default: score]
2020
--repetitions REPETITIONS Repetitions in objective [default: 100]
2121
--turns TURNS Turns in each match [default: 200]
@@ -149,15 +149,15 @@ def __repr__(self):
149149
@classmethod
150150
def parse_repr(cls, s):
151151
rows = []
152-
lines = rep.split(':')
152+
lines = s.split(':')
153153
initial_state = int(lines[0])
154154
initial_action = lines[1]
155155

156156
for line in lines[2:]:
157157
row = line.split('_')
158158
rows.append(row)
159159
num_states = len(rows) // 2
160-
return cls(num_states, rows, initial_state, initial_action)
160+
return cls(num_states, 0.1, rows, initial_state, initial_action)
161161

162162

163163
if __name__ == '__main__':

hmm_evolve.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
--mu MUTATION_RATE Mutation rate [default: 0.1]
1616
--bottleneck BOTTLENECK Number of individuals to keep from each generation [default: 10]
1717
--processes PROCESSES Number of processes to use [default: 1]
18-
--output OUTPUT_FILE File to write data to [default: fsm_tables.csv]
18+
--output OUTPUT_FILE File to write data to [default: hmm_params.csv]
1919
--objective OBJECTIVE Objective function [default: score]
2020
--repetitions REPETITIONS Repetitions in objective [default: 100]
2121
--turns TURNS Turns in each match [default: 200]
@@ -118,7 +118,8 @@ def random_params(num_states):
118118
t_C.append(random_vector(num_states))
119119
t_D.append(random_vector(num_states))
120120
initial_state = randrange(num_states)
121-
initial_action = choice([C, D])
121+
# initial_action = choice([C, D])
122+
initial_action = C
122123
return t_C, t_D, initial_state, initial_action
123124

124125
def randomize(self):
@@ -178,7 +179,7 @@ def repr_rows(rows):
178179
ss = []
179180
for row in rows:
180181
ss.append("_".join(list(map(str, row))))
181-
return ":".join(ss)
182+
return "|".join(ss)
182183

183184
def __repr__(self):
184185
return "{}:{}:{}:{}:{}".format(
@@ -189,18 +190,23 @@ def __repr__(self):
189190
self.repr_rows([self.emission_probabilities])
190191
)
191192

192-
# @classmethod
193-
# def parse_repr(cls, s):
194-
# rows = []
195-
# lines = rep.split(':')
196-
# initial_state = int(lines[0])
197-
# initial_action = lines[1]
198-
#
199-
# for line in lines[2:]:
200-
# row = line.split('_')
201-
# rows.append(row)
202-
# num_states = len(rows) // 2
203-
# return cls(num_states, rows, initial_state, initial_action)
193+
@classmethod
194+
def parse_repr(cls, s):
195+
def parse_matrix(sm):
196+
rows = []
197+
lines = sm.split('|')
198+
for line in lines:
199+
row = line.split('_')
200+
row = list(map(float, row))
201+
rows.append(row)
202+
return row
203+
lines = s.split(':')
204+
initial_state = int(lines[0])
205+
initial_action = lines[1]
206+
t_C = parse_matrix(lines[2])
207+
t_D = parse_matrix(lines[3])
208+
ps = parse_matrix(lines[4])
209+
return cls(t_C, t_D, ps, initial_state, initial_action)
204210

205211

206212
if __name__ == '__main__':

lookup_evolve.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
Options:
1111
-h --help Show help
1212
--generations GENERATIONS Generations to run the EA [default: 500]
13-
--population POPULATION Starting population size [default: 10]
13+
--population POPULATION Starting population size [default: 40]
1414
--mu MUTATION_RATE Mutation rate [default: 0.1]
15-
--bottleneck BOTTLENECK Number of individuals to keep from each generation [default: 5]
15+
--bottleneck BOTTLENECK Number of individuals to keep from each generation [default: 10]
1616
--processes PROCESSES Number of processes to use [default: 1]
17-
--output OUTPUT_FILE File to write data to [default: lookup_tables.csv]
17+
--output OUTPUT_FILE File to write data to [default: lookup_params.csv]
1818
--objective OBJECTIVE Objective function [default: score]
1919
--repetitions REPETITIONS Repetitions in objective [default: 100]
2020
--turns TURNS Turns in each match [default: 200]
@@ -131,7 +131,8 @@ def __repr__(self):
131131
@classmethod
132132
def parse_repr(cls, s):
133133
elements = s.split(':')
134-
plays, op_plays, op_start_plays, initial_actions, pattern = elements
134+
plays, op_plays, op_start_plays = list(map(int, elements[:3]))
135+
initial_actions, pattern = elements[-2:]
135136
keys = create_lookup_table_keys(plays, op_plays, op_start_plays)
136137
table = dict(zip(keys, pattern))
137138
return cls(plays, op_plays, op_start_plays,

pso_evolve.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
Options:
1616
-h --help Show help
1717
--generations GENERATIONS Generations to run the EA [default: 100]
18-
--population POPULATION Starting population size [default: 100]
18+
--population POPULATION Starting population size [default: 40]
1919
--processes PROCESSES Number of processes to use [default: 1]
2020
--output OUTPUT_FILE File to write data to [default: pso_tables.csv]
2121
--objective OBJECTIVE Objective function [default: score]

tests.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
import unittest
3+
4+
from hmm_evolve import HMMParams
5+
from ann_evolve import ANNParams
6+
from fsm_evolve import FSMParams
7+
from lookup_evolve import LookerUpParams
8+
from evolve_utils import load_params
9+
10+
class TestRepr(unittest.TestCase):
11+
12+
def test_repr_load(self):
13+
for params_class, filename in [
14+
(ANNParams, "ann_params.csv"),
15+
(LookerUpParams, "lookup_params.csv"),
16+
(FSMParams, "fsm_params.csv"),
17+
(HMMParams, "hmm_params.csv")
18+
]:
19+
print(filename)
20+
params = load_params(params_class, filename, 10)
21+

0 commit comments

Comments
 (0)