Skip to content

Instantly share code, notes, and snippets.

@fedden
Created December 11, 2017 09:55
Show Gist options
  • Save fedden/49afe079897346d533219ed625da61e4 to your computer and use it in GitHub Desktop.
Save fedden/49afe079897346d533219ed625da61e4 to your computer and use it in GitHub Desktop.
class GA():
def __init__(self,
dna_size,
elitism=0.01,
population_size=200,
mutation_rate=0.01,
mutation_sigma=0.1,
mutation_decay=0.999,
mutation_limit=0.01,
mutate_fn=None,
crossover_fn=None):
self.population = self.__create_random_population(dna_size,
mutation_sigma,
population_size)
self.fitnesses = np.zeros_like(self.population)
self.best_dna = None
self.best_fitness = None
self.elitism = elitism
self.population_size = population_size
self.mutation_rate = mutation_rate
self.mutation_sigma = mutation_sigma
self.mutation_decay = mutation_decay
self.mutation_limit = mutation_limit
self.mutate_fn = mutate_fn
self.crossover_fn = crossover_fn
def get_solutions(self):
return self.population
def set_fitnesses(self, fitnesses):
assert len(fitnesses) == len(self.fitnesses)
self.fitnesses = np.array(fitnesses)
fitnesses_indices = (-self.fitnesses).argsort()
sorted_fitnesses = self.fitnesses[fitnesses_indices]
fitnesses_weighting = np.maximum(0, 1 - sorted_fitnesses / self.fitnesses.sum())
fitnesses_weighting /= fitnesses_weighting.sum()
sorted_population = self.population[fitnesses_indices]
self.best_dna = sorted_population[0]
self.best_fitness = sorted_fitnesses[0]
amount_new = int((1 - self.elitism) * len(self.population))
new_population = []
for _ in range(amount_new):
i0 = np.random.choice(sorted_population.shape[0], p=fitnesses_weighting)
i1 = np.random.choice(sorted_population.shape[0], p=fitnesses_weighting)
new_dna = self.__crossover(self.population[i0], self.population[i1])
new_dna = self.__mutate(new_dna, self.mutation_sigma, self.mutation_rate)
new_population.append(new_dna)
amount_old = population_size - amount_new
new_population = np.array(new_population + sorted_population[:amount_old].tolist())
assert new_population.shape == self.population.shape
def get_best(self):
return self.best_dna, self.best_fitness
def __create_random_population(self,
dna_size,
dna_sigma,
population_size):
print(dna_size, population_size)
population = np.random.randint(2, size=(population_size, dna_size))
return population
def __mutate(self,
dna,
mutation_sigma,
mutation_rate):
if self.mutate_fn is not None:
return self.mutate_fn(dna)
if np.random.random_sample() < mutation_rate:
dna = np.random.randint(2, size=dna.size)
return dna
def __crossover(self, dna1, dna2):
assert len(dna1) == len(dna2)
if self.crossover_fn is not None:
return self.crossover_fn(dna1, dna2)
new_dna = np.copy(dna1)
indices = np.where(np.random.randint(2, size=new_dna.size))
new_dna[indices] = dna2[indices]
return new_dna
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment