-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathgenerate_cache.py
133 lines (109 loc) · 3.9 KB
/
generate_cache.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
from collections import defaultdict, Counter
import csv
import functools
import multiprocessing
import os
import axelrod as axl
def write_csv(outcomes, filename="outcomes.csv", append=False):
s = 'w'
if append:
s = 'a'
writer = csv.writer(open(filename, s))
for pair, counter in outcomes.items():
for scores, count in counter.items():
row = [pair[0], pair[1], scores[0], scores[1], count]
writer.writerow(row)
def read_csv(filename="outcomes.csv"):
reader = csv.reader(open(filename))
outcomes = defaultdict(Counter)
for row in reader:
p1, p2, s1, s2, count = row
outcomes[(p1, p2)][(float(s1), float(s2))] = int(count)
outcomes[(p2, p1)][(float(s2), float(s1))] = int(count)
return outcomes
def generate_matchups(players):
# Want the triangular product
for i, j in generate_matchups_indices(len(players)):
if i == j:
yield players[i].clone(), players[j]
else:
yield players[i], players[j]
def generate_matchups_indices(num_players):
# Want the triangular product
for i in range(num_players):
for j in range(i, num_players):
yield i, j
def sample_match_outcomes(players, turns, repetitions, noise=0):
"""
Play all matches between pairs of players and return a dictionary mapping
player names to outcomes.
"""
match_outcomes = dict()
matchups = list(generate_matchups(players))
for pairs in matchups:
match = axl.Match(pairs, turns=turns, noise=noise)
rs = repetitions
if not match._stochastic:
rs = 1
outcomes = []
for _ in range(rs):
match.play()
outcomes.append(match.final_score_per_turn())
counts = Counter(outcomes)
player_names = tuple(map(str, pairs))
match_outcomes[player_names] = counts
return match_outcomes
def write_winner(filename, turns, repetitions, noise, i, j, seed=None):
"""
Write the scores of a match between two players to file
"""
if seed:
axl.seed(seed) # Seed the process
pairs = (players[i].clone(), players[j].clone())
match = axl.Match(pairs, turns=turns, noise=noise)
rs = repetitions
if not match._stochastic and noise == 0:
rs = 1
outcomes = []
for _ in range(rs):
match.play()
outcomes.append(match.final_score_per_turn())
counts = Counter(outcomes)
player_names = tuple(map(str, pairs))
match_outcomes = dict()
match_outcomes[player_names] = counts
write_csv(match_outcomes, filename=filename, append=True)
def sample_match_outcomes_parallel(turns, repetitions, filename, noise=0,
processes=None):
"""
Parallel matches.
"""
player_indices = range(len(players))
if processes is None:
for i in player_indices:
print(i, len(players))
for j in player_indices:
for seed in range(repetitions):
write_winner(filename, turns, repetitions, noise, i, j,
seed)
else:
func = functools.partial(write_winner, filename, turns, repetitions,
noise)
p = multiprocessing.Pool(processes)
args = generate_matchups_indices(len(players))
p.starmap(func, args)
if __name__ == "__main__":
# players are global
from players import selected_players
players = selected_players()
print(len(list(map(str, players))))
try:
os.remove("../data/missing_fsm_outcomes.csv")
except FileNotFoundError:
pass
repetitions = 1000
turns = 200
cpu_count = multiprocessing.cpu_count()
sample_match_outcomes_parallel(turns=turns, repetitions=repetitions,
filename="../data/missing_fsm_outcomes.csv", noise=0,
processes=cpu_count)