-
Notifications
You must be signed in to change notification settings - Fork 0
/
genetic.py
117 lines (99 loc) · 3.18 KB
/
genetic.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
# Tanmai Kalisipudi & Griff Boehnlein
# 1/23/23
# issues to fix:
# 1. clones were too high
# 2. make sure that the population is being updated correctly
# 3. change so that the child is not randomly flip flopped but is an avergae of the two instead
import time
from naive import naive
from random import random, choice
import sys
from tqdm import tqdm
POPULATION_SIZE = 50
NUM_CLONES = 3
MUTATION_RATE = .2
TOURNAMENT_SIZE = 20
TOURNAMENT_WIN_PROBABILITY = .75
NUM_GENERATIONS = 1
# Functions needed:
# fitness(weights)
# generate_random_weights()
# generate_initial_population()
# rank_population()
# breed(mom, dad)
def fitness(strategy):
return naive(strategy)
def generate_random_weights():
return [random() for x in range(14)]
def init_population():
return [generate_random_weights() for x in range(POPULATION_SIZE)]
def rank_population(population):
strat_to_fitness = dict()
for index, strategy in enumerate(population):
strat_to_fitness[index] = fitness(strategy)
ranked = sorted(strat_to_fitness.items(), key = lambda kv : (kv[1], kv[0]))
return ranked[::-1]
def mutate(child):
for index, weight in enumerate(child):
if random() < MUTATION_RATE:
child[index] = random()
return child
def breed(mom, dad):
child = []
for i in range(len(mom)):
if random() < .5:
child.append(mom[i])
else:
child.append(dad[i])
return child
def create_child(current_population):
full_tourney = []
while len(full_tourney) < (TOURNAMENT_SIZE * 2):
toAdd = choice(current_population)
if toAdd not in full_tourney:
full_tourney.append(toAdd)
tourney1 = full_tourney[:TOURNAMENT_SIZE]
tourney2 = full_tourney[TOURNAMENT_SIZE:]
tourney1.sort(key=lambda x:x[1])
tourney2.sort(key=lambda x:x[1])
tourney1 = tourney1[::-1]
tourney2 = tourney2[::-1]
parent1 = 0
parent2 = 0
for element in enumerate(tourney1):
if random() <= TOURNAMENT_WIN_PROBABILITY:
parent1 = popCurrent[element[0]]
break
for element in enumerate(tourney2):
if random() <= TOURNAMENT_WIN_PROBABILITY:
parent2 = popCurrent[element[0]]
break
if parent1 == 0:
# print("couldn't find parent 1")
parent1 = popCurrent[tourney1[0][0]]
if parent2 == 0:
# print("couldn't find parent 2")
parent2 = popCurrent[tourney2[0][0]]
child = breed(parent1, parent2)
if random() < MUTATION_RATE:
child = mutate(child)
return child
popZero = init_population()
popCurrent = popZero
print(popCurrent)
# for x in range(NUM_GENERATIONS):
for x in range(2):
newPop = []
rankedPop = rank_population(popCurrent)
for clone in range(NUM_CLONES):
newPop.append(popCurrent[clone])
while len(newPop) < POPULATION_SIZE:
child = create_child(rankedPop)
if child not in newPop:
newPop.append(child)
popCurrent = newPop.copy()
newPop = []
print("Generation " + str(x) + " complete")
rankedPop = rank_population(popCurrent)
best_strategy = rankedPop[0][0]
print("Best strategy accuracy: " + str(fitness(popCurrent[best_strategy])))