112 lines
3.2 KiB
Python
112 lines
3.2 KiB
Python
from individual import Individual
|
|
from random import Random
|
|
|
|
rand = Random()
|
|
|
|
|
|
class Population(object):
|
|
|
|
def __init__(self, size):
|
|
self.members = list()
|
|
for current in range(0, size):
|
|
self.members.append(Individual())
|
|
|
|
def __str__(self):
|
|
return_string = ""
|
|
position = 0
|
|
for member in self.members:
|
|
return_string += "%d:\tx: %e\ty: %e\tfit: %e\n" %\
|
|
(position, member.x, member.y, member.fitness())
|
|
position += 1
|
|
return_string += "Average fit:\t%e\n" % self.avg_fitness()
|
|
best = self.best_fitness()
|
|
return_string += "Best fit:\tx:%e,\ty:%e\tf:%e" %\
|
|
(best.x, best.y, best.fitness())
|
|
return return_string
|
|
|
|
def total_fitness(self, members=None):
|
|
total = 0
|
|
|
|
if members is None:
|
|
members = self.members
|
|
|
|
for member in members:
|
|
total += member.fitness()
|
|
|
|
return total
|
|
|
|
def avg_fitness(self):
|
|
return float(self.total_fitness() / len(self.members))
|
|
|
|
def best_fitness(self):
|
|
return self.best_member().fitness()
|
|
|
|
def best_member(self):
|
|
best_member = self.members[0]
|
|
|
|
for member in self.members:
|
|
if float(member.fitness()) > best_member.fitness():
|
|
best_member = member
|
|
return best_member
|
|
|
|
def roulette(self, members=None):
|
|
total = self.total_fitness(members=members)
|
|
position = rand.uniform(0, total)
|
|
|
|
if members is None:
|
|
members = self.members
|
|
|
|
for member in members:
|
|
position -= member.fitness()
|
|
if position <= 0:
|
|
return member
|
|
|
|
def mutate(self, chance):
|
|
for member in self.members:
|
|
if rand.random() < chance/100:
|
|
member.mutate()
|
|
|
|
def elite(self, amount):
|
|
sorted_members = sorted(self.members, key=lambda
|
|
x: x.fitness(), reverse=True)[:amount]
|
|
|
|
return sorted_members
|
|
|
|
def advance_generation(self, n_elite, crossover_rate=0.5, n_arena=4, mutation=0):
|
|
new_generation = list()
|
|
|
|
while len(new_generation) < len(self.members) - n_elite:
|
|
if n_arena > 0:
|
|
x, y = self.tournament_selection(n_arena, crossover_rate)
|
|
|
|
new_generation.append(x)
|
|
new_generation.append(y)
|
|
|
|
# Remove excess members
|
|
while len(new_generation) > len(self.members) - n_elite:
|
|
new_generation.pop()
|
|
|
|
for member in new_generation:
|
|
if rand.random() < mutation/100:
|
|
member.mutate()
|
|
|
|
# elitism
|
|
new_generation += self.elite(n_elite)
|
|
|
|
self.members = new_generation
|
|
|
|
def remove_member(self, member):
|
|
self.members.remove(member)
|
|
|
|
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]
|