-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathevolution_1010.py
180 lines (160 loc) · 4.91 KB
/
evolution_1010.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
from player_1010 import *
#Sets player names and appends each player to the players list
def rename(players):
for x in range(len(players)):
players[x].name = "Candidate " + str(x + 1)
def randomize_weights(player):
"""Totally scrambles the weights of a player's strategy functions to a
value from -10 to 10 step by 0.1"""
for x in range(len(player.weights)):
player.weights[x] = main_rand.randrange(-100,101)/10
return player
def avg(*args):
return(sum(args)/len(args))
def avg_l(l):
return(sum(l)/len(l))
def avg_w(*players):
P = Player()
weights = []
for x in P.weights:
weights.append([])
for player in players:
for x in range(len(player.weights)):
weights[x].append(player.weights[x])
for x in range(len(P.weights)):
P.weights[x]=avg_l(weights[x])
return P
def gene_mix(*players):
P = Player()
weights = []
for x in P.weights:
weights.append([])
for player in players:
for x in range(len(player.weights)):
weights[x].append(player.weights[x])
for x in range(len(P.weights)):
P.weights[x]=main_rand.choice(weights[x])
return P
def breed(*players):
P = gene_mix(*players)
return mutate_shift(P)
def mutate_shift(player):
"""creates a copy of the given player, with slight mutations"""
P = Player()
for x in range(len(player.weights)):
P.weights[x]=player.weights[x]+main_rand.randrange(-20,21)/10
return P
def mutate_all(old_players, scores):
"""mutates the players table (see diagram for details)"""
num_candidates = len(old_players)
ziplist = list(zip(old_players, scores))
ziplist.sort(reverse=True, key = lambda x: avg_l(x[1]))
c1 = ziplist[0][0]
c2 = ziplist[1][0]
c3 = ziplist[2][0]
c4 = breed(c1, c2)
c5 = breed(c2, c3)
c6 = breed(c1, c3)
c7 = breed(c1, c2, c3)
c8 = mutate_shift(c1)
c9 = mutate_shift(c7)
c10 = randomize_weights(Player())
players = [c1,c2,c3,c4,c5,c6,c7,c8,c9,c10]
if num_candidates < 10:
return players[:num_candidates]
elif num_candidates == 10:
return players
else:
for x in range(num_candidates-10):
players.append(randomize_weights(Player()))
return players
def run_sim(player, seed, scorehistory):
player.seed = seed
key = (tuple(player.weights),seed)
if key in scorehistory:
return scorehistory[key]
else:
score = player.play()
scorehistory[key] = score
return score
#The initial scrambling of all the candidates
def initial_scramble(players):
for player in players:
randomize_weights(player)
return
#The players table contains the candidates
def intialize_players_list(num_candidates):
players = []
for x in range(num_candidates):
P = Player()
players.append(P)
rename(players)
return players
#Run the evolution for the desired number of generations
def run_evolution(num_generations, num_candidates, board_seeds, *starting_weights):
#initialize everything
scoredict = dict()
players = intialize_players_list(num_candidates)
initial_scramble(players)
player_scores = []
#set given starting weights
player_index = 0
for weight_list in starting_weights:
players[player_index].adopt_weights(weight_list)
player_index += 1
#Generation loop
top_hiscore = 0
top_average = 0
top_weights = []
for x in range(num_generations):
print("Starting Generation",x)
player_scores = []
for player in players:
scores = []
print(" "+player.name+" Weights:"+str(player.weights))
for seed in board_seeds:
score = run_sim(player, seed, scoredict)
scores.append(score)
print(" ",player.name,"Final Score:", score, "Seed:", player.seed)
average = avg_l(scores)
hiscore = max(scores)
print(" AVERAGE =",average)
print(" HISCORE =",hiscore)
print()
player_scores.append((average,hiscore))
print("Top performer of Generation",x)
top_player_score = max(player_scores, key=lambda x: avg(x[0],x[1]))
i = player_scores.index(top_player_score)
top = players[i]
top_weights = top.weights
top_hiscore = player_scores[i][1]
top_average = player_scores[i][0]
print("NAME:",top.name)
print("WEIGHTS:",top_weights)
print("HISCORE:",top_hiscore)
print("AVERAGE:",top_average)
print()
players = mutate_all(players, player_scores)
for player in players:
for x in range(len(player.weights)):
player.weights[x] = round(player.weights[x],1)
rename(players)
#print and return results
print("""Most effective weights: {}
Highest Score: {}
Average Score: {}""".format(top_weights, top_hiscore, top_average))
return top_weights
# BEST WEIGHTS YET [14.2, 0.6, 0.2, 1.5, 5.1, -0.3]
def main():
known_good_weights = []#[14.2, 0.6, 0.2, 1.5, 5.1, -0.3,0]]
"""[13.4, 0.2, -0.7, 5.8, 5.1, -1.0],
[8.7, -6.9, 6.1, 0.5, 6.2, -1.5],
[6.0, -5.2, 9.0, -9.6, 9.5, -4.3],
[14.3, 1.2, 0.6, 3.5, 7.6, -0.3],
[14.2, 0.6, 0.2, 1.5, 5.1, -0.3],
[13.9, -0.1, 0.7, 3.2, 5.8, -0.8]]"""
#weights = run_evolution(20, 20, list(range(10)), *known_good_weights)
weights = run_evolution(40, 20, [1004,1005,1006,1007,1008,1009,1010], *known_good_weights)
if __name__ == "__main__":
main_rand = Random()
main()