Implement tournament selection

This commit is contained in:
George Lacey 2017-10-13 16:20:58 +01:00
parent 4b1a9c3709
commit 300678156c
4 changed files with 44 additions and 26 deletions

View File

@ -33,8 +33,7 @@ class Individual(object):
return one, two return one, two
def mutate(self): def mutate(self):
rand.randint(1, 10) if rand.random() < 0.5:
if rand.randint(1, 10) % 2 == 0:
self.x = self.get_rand_param() self.x = self.get_rand_param()
else: else:
self.y = self.get_rand_param() self.y = self.get_rand_param()

View File

@ -9,14 +9,21 @@ class Lifecycle(object):
self.population = Population(self.params["population_size"]) self.population = Population(self.params["population_size"])
self.best_fit = list() self.best_fit = list()
self.average_fit = list() self.average_fit = list()
self.iterations = 0
def start(self): def start(self):
for epoch in range(0, self.params["iter"]): for epoch in range(0, self.params["epochs"]):
self.iterations += 1
elite = self.params["elite"] elite = self.params["elite"]
crossover = self.params["crossover"] crossover = self.params["crossover"]
self.population.advance_generation(elite, crossover) self.population.advance_generation(elite, crossover_rate=crossover, n_arena=4)
self.best_fit.append(self.population.best_fitness()) self.best_fit.append(self.population.best_fitness())
self.average_fit.append(self.population.avg_fitness()) self.average_fit.append(self.population.avg_fitness())
if epoch > 50:
recent_best = self.best_fit[-50:]
if max(recent_best) - min(recent_best) < 0.02:
break
def best_fitness(self): def best_fitness(self):
return self.population.best_fitness() return self.population.best_fitness()
@ -33,4 +40,5 @@ class Lifecycle(object):
def get_csv(self): def get_csv(self):
id = {'id': self.id} id = {'id': self.id}
best_fitness = {'best_fit': self.best_fitness()} best_fitness = {'best_fit': self.best_fitness()}
return {**id, **best_fitness, **self.params} iter = {'iter': self.iterations}
return {**id, **best_fitness, **self.params, **iter}

View File

@ -8,14 +8,15 @@ import time
param_example = {'population_size': 10, param_example = {'population_size': 10,
'elite': round(0.1 * 10), 'elite': round(0.1 * 10),
'crossover': round(0.6 * 10), 'crossover': round(0.6 * 10),
'iter': 1000} 'epochs': 1000,
'iter': 0}
def gen_param(pop, elite, crossover, iter): def gen_param(pop, elite, crossover, epochs):
return {'population_size': pop, return {'population_size': pop,
'elite': round(elite * pop), 'elite': round(elite * pop),
'crossover': round(crossover * pop), 'crossover': round(crossover * pop),
'iter': iter} 'epochs': epochs}
outputs = Queue() outputs = Queue()
@ -39,9 +40,9 @@ instances = list()
id = 0 id = 0
for i in [x * 0.01 for x in range(20, 80, 5)]: for i in [x * 1 for x in range(0, 100)]:
instances.append(Process(name="Thread-%d" % i, target=run_instance, instances.append(Process(name="Thread-%d" % i, target=run_instance,
args=[Lifecycle(id, gen_param(20, 0.1, i, 50)), outputs])) args=[Lifecycle(id, gen_param(50, 0, 0.5, 500)), outputs]))
id += 1 id += 1
start_time = time.time() start_time = time.time()
@ -50,7 +51,7 @@ for instance in instances:
instance.start() instance.start()
while len([t for t in instances if t.is_alive()]) != 0: while len([t for t in instances if t.is_alive()]) != 0:
print("here") print("Processes left: %d" % len([t for t in instances if t.is_alive()]))
sleep(1) sleep(1)
end_time = time.time() end_time = time.time()
@ -61,5 +62,3 @@ while not outputs.empty():
output_file.close() output_file.close()
print("Execution took %f seconds" % (end_time - start_time)) print("Execution took %f seconds" % (end_time - start_time))
#ga.generate_graph(show=True)

View File

@ -72,7 +72,7 @@ class Population(object):
return sorted_members return sorted_members
def advance_generation(self, n_elite, n_crossover): def advance_generation(self, n_elite, crossover_rate=0.5, n_arena=4):
new_generation = list() new_generation = list()
# elitism # elitism
@ -80,25 +80,37 @@ class Population(object):
new_generation.append(member) new_generation.append(member)
# parent # parent
for ind in range(0, n_crossover): # for ind in range(0, n_crossover):
parent_one = self.roulette() # self.roulette_crossover(new_generation)
parent_two = self.roulette()
x, y = parent_one.crossover(parent_two)
new_generation.append(x)
new_generation.append(y)
while len(new_generation) < len(self.members): while len(new_generation) < len(self.members):
new_generation.append(self.roulette()) if n_arena > 0:
x, y = self.tournament_selection(n_arena, crossover_rate)
else:
x, y = self.roulette_crossover()
new_generation.append(x)
new_generation.append(y)
self.members = new_generation self.members = new_generation
self.mutate(10) self.mutate(10)
self.check_termination()
def remove_member(self, member): def remove_member(self, member):
self.members.remove(member) self.members.remove(member)
def check_termination(self): def roulette_crossover(self):
# todo: complete parent_one = self.roulette()
pass parent_two = self.roulette()
return parent_one.crossover(parent_two)
def tournament_selection(self, arena_size, rate):
parents = list()
for i in range(arena_size):
parents.append(self.members[rand.randint(0, len(self.members) - 1)])
parents = sorted(parents, key=lambda x: x.fitness(), reverse=True)
if rand.random() < rate:
return parents[0].crossover(parents[1])
else:
return parents[0], parents[1]