-
Notifications
You must be signed in to change notification settings - Fork 0
/
genetic_algorithm.py
184 lines (131 loc) · 4.7 KB
/
genetic_algorithm.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
180
181
182
183
184
"""
@author Viktor Ciroski
"""
"""
Genetic Algorithm Layout
Population
Fitness Calculation
Matting Pool
Parent Seleciton
Matting
Crossover
Mutation
Offspring
"""
import random
import datetime
from operator import itemgetter
import random
class Progeny():
def __init__(self, geneSet, mutation, crossover, keep):
self.geneSet = geneSet
self.mutation = mutation
self.crossover_chance = crossover
self.keep_rate = keep
self.length = None
def generate_parent(self, length):
self.length = length
genes = []
while(len(genes)<length):
sampleSize=min(length-len(genes), len(self.geneSet))
genes.extend(random.sample(self.geneSet, sampleSize))
return ''.join(genes)
def mutate(self, parent):
newGene = ''
for i in range(len(parent)):
gene = random.sample(self.geneSet, 1)
newGene += gene[0]
return newGene
def crossover(self, father, mother):
#netwrok_bit_size = len(father)
#print(netwrok_bit_size)
#print(mother)
print("\n\n------------------------------------------------\n")
print("Mother Len", len(mother))
#print(father)
print("Father len", len(father))
print("OG len", self.length)
baby = ''
i = 0
#Uniform Crossover operation between both parents
while len(baby) < self.length:
probability = random.uniform(0,1)
if probability < self.crossover_chance:
if father[i] == 1 or father[i] == 0:
print("adding FATHER gene")
baby += (father[i])
i += 1
elif probability < (2*self.crossover_chance):
if mother[i] == 1 or mother[i] == 0:
print("adding MOTHER gene")
baby += (mother[i])
i += 1
else:
#mutation Probability
gene = [random.randint(0, 1)]
mutatedProbability = random.uniform(0,1)
if mutatedProbability > self.mutation:
mutated_gene = (self.mutate(gene))
if mutated_gene == 1 or mutated_gene ==0:
print("MUTATING a gene")
baby += (mutated_gene)
i += 1
else:
if gene[0] == 1 or gene[0] == 0:
print("adding RANDOM gene")
baby += str(gene[0])
i += 1
print("BABY GENOME")
print(baby)
print("Baby len", len(baby))
print("\n\n------------------------------------------------\n")
return baby
def population(self, count, length):
pop = []
for _ in range(0, count):
network = self.generate_parent(length)
pop.append(network)
return pop
def fitness(network):
"""Return the accuracy, which is our fitness function."""
return network.f1
def Offspring(self, population):
size_of_pop = len(population)
#sort by most accurate to least
graded = sorted(population, key=itemgetter(1), reverse=True)
best_acc = graded[0][1]
#keep N parents
keep = int(size_of_pop*self.keep_rate)
if keep == 0:
keep = 1
graded_binary = []
for i in range(len(graded)):
graded_binary.append(graded[i][0])
#print(graded_binary)
graded_best = graded_binary[:keep]
#print(graded_best)
#randomly keep some less accurate parents for diversity
retain_non_best = int((size_of_pop - keep) * self.keep_rate)
for _ in range(random.randint(0, retain_non_best)):
graded_best.append(random.choice(graded_binary[keep:]))
#fill remaining spots with next evolution
counter = 0
#print(size_of_pop)
#print("inital")
while len(graded_best) < size_of_pop:
#print("Coutner", counter)
counter += 1
baby = None
if len(graded_best) == 1:
baby = self.mutate(graded_best[0])
#print(graded_best)
idx_1 = random.randint(0, len(graded_best)-1)
idx_2 = random.randint(0, len(graded_best)-1)
papi = graded_best[idx_1]
daddy = graded_best[idx_2]
if daddy != papi:
baby = self.crossover(papi, daddy)
if baby != None:
graded_best.append(baby)
#print(graded_best)
return graded_best, best_acc