44 lines
1.5 KiB
Python
44 lines
1.5 KiB
Python
|
import random
|
||
|
import numpy as np
|
||
|
|
||
|
|
||
|
# Let's solve the function f(x, y) = -2x^2 - 3(y - 4)^2
|
||
|
def fitness(x):
|
||
|
return -2 * (x[:, 0] ** 2) - 3 * (x[:, 1] - 4)**2
|
||
|
|
||
|
class Population:
|
||
|
def __init__(self, initial_guess, population_size, fitness_fn, learning_rate = 1e-4, sigma = 0.1):
|
||
|
self.current_solution = initial_guess
|
||
|
self.population_size = population_size
|
||
|
self.sigma = sigma
|
||
|
self.learning_rate = learning_rate
|
||
|
assert self.population_size > 0
|
||
|
assert self.sigma >= 0
|
||
|
self.calculate_fitness = fitness_fn
|
||
|
|
||
|
|
||
|
def __iter__(self):
|
||
|
return self
|
||
|
|
||
|
# This function is suppose to take us to the next generation
|
||
|
def __next__(self):
|
||
|
white_noise = np.random.randn(self.population_size, *self.current_solution.shape)
|
||
|
noise = self.sigma * white_noise
|
||
|
candidate_solutions = self.current_solution + noise
|
||
|
fitness_values = self.calculate_fitness(candidate_solutions)
|
||
|
# Mean shift and scale
|
||
|
fitness_values = (fitness_values - np.mean(fitness_values)) / (np.std(fitness_values) + np.finfo('float').eps)
|
||
|
new_solution = self.current_solution + self.learning_rate * np.mean(white_noise.T * fitness_values, axis = 1) / self.sigma
|
||
|
self.current_solution = new_solution
|
||
|
return new_solution
|
||
|
|
||
|
def item(self):
|
||
|
return self.current_solution
|
||
|
|
||
|
|
||
|
def test():
|
||
|
guess = np.random.randn(2)
|
||
|
p = Population(guess, 100, fitness)
|
||
|
for i in range(10000):
|
||
|
next(p)
|
||
|
return p.item()
|