Reputation: 18
Im trying to recreate this code: https://github.com/Code-Bullet/Smart-Dots-Genetic-Algorithm-Tutorial/tree/master/BestTutorialEver , but in python, and it doesn't work, it keeps mutating the best dot and every generation starts with less dots. Here is the code (i use pygame for graphics):
Brain class:
class Brain(object):
def __init__(self, size):
self.size = size
self.step = 0
self.directions = [[0.0, 0.0] for j in range(size)]
for i in range(len(self.directions)):
randomAngle = random.uniform(0, 2 * math.pi)
self.directions[i][0] = math.sin(randomAngle)
self.directions[i][1] = math.cos(randomAngle)
def mutate(self):
mutationRate = 1
for i in range(self.size):
rand = random.random()
if rand < mutationRate:
dirAngle = math.acos(self.directions[i][1]) * (1.0 + random.random())
self.directions[i][0] = math.sin(dirAngle)
self.directions[i][1] = math.cos(dirAngle)
Population Class:
class Population(object):
def __init__(self, size, win):
self.bestDot = 0
self.fitnessSum = 0.0
self.win = win
self.size = size
self.dots = [Dot(win) for i in range(size)]
def show(self):
for i in range(self.size-1):
self.dots[i+1].show()
self.dots[0].show()
def updt(self):
for i in range(self.size):
self.dots[i].updt()
def calculateFitness(self):
for i in range(self.size):
self.dots[i].calculateFitness()
def allDotsDead(self):
for i in range(self.size):
if not self.dots[i].dead and not self.dots[i].reachGoal:
return False
return True
def naturalSelection(self):
newDots = [Dot(self.win) for i in range(self.size)]
self.setBestDot()
self.calculateFitnessSum()
newDots[0] = self.dots[self.bestDot].baby()
newDots[0].isBest = True
for i in range(self.size-1):
parent = self.selectParent()
newDots[i+1] = parent.baby()
print(newDots[1])
self.dots = newDots
def calculateFitnessSum(self):
self.fitnessSum = 0.0
for i in range(self.size):
self.fitnessSum += self.dots[i].fitness
print(self.fitnessSum)
def selectParent(self):
rand = random.uniform(0, self.fitnessSum)
runningSum = 0.0
for i in range(self.size):
runningSum += self.dots[i].fitness
if runningSum >= rand:
return self.dots[i]
return None
def mutate(self):
for i in range(self.size):
if not self.dots[i].isBest:
self.dots[i].brain.mutate()
def setBestDot(self):
max = 0.0
maxIndex = 0
for i in range(len(self.dots)):
if self.dots[i].fitness > max:
max = self.dots[i].fitness
maxIndex = i
self.bestDot = maxIndex
Dot Class:
WIDTH, HEIGHT = 720, 640
GOAL = (WIDTH / 2, 50)
class Dot(object):
def __init__(self, win):
self.win = win
self.fitness = 0
self.reachGoal = False
self.dead = False
self.brain = Brain(200)
self.pos = [WIDTH / 2, HEIGHT - 50]
self.vel = [0, 0]
self.acc = [0, 0]
self.isBest = False
def move(self):
if len(self.brain.directions) > self.brain.step:
self.acc = self.brain.directions[self.brain.step]
self.brain.step += 1
else:
self.dead = True
for i in range(len(self.vel)): self.vel[i] += self.acc[i]
if self.vel[0] >= 5: self.vel[0] = 5
if self.vel[1] >= 5: self.vel[1] = 5
for i in range(len(self.pos)): self.pos[i] += self.vel[i]
def show(self):
if self.isBest:
pygame.draw.circle(self.win, (0, 255, 0), self.pos, 4)
else:
pygame.draw.circle(self.win, (200, 100, 0), self.pos, 2)
def updt(self):
if not self.dead and not self.reachGoal:
self.move()
if self.pos[0] < 4 or self.pos[1] < 4 or self.pos[0] > WIDTH - 4 or self.pos[1] > HEIGHT - 4:
self.dead = True
elif math.hypot(self.pos[0] - GOAL[0], self.pos[1] - GOAL[1]) < 5:
self.reachGoal = True
def calculateFitness(self):
distToGoal = math.hypot(self.pos[0] - GOAL[0], self.pos[1] - GOAL[1])
self.fitness = 1.0 / 16.0 + 10000.0 / (distToGoal * distToGoal)
def baby(self):
baby = Dot(self.win)
baby.brain.directions = self.brain.directions
return baby
The problem is that i especify that the best dot dont mutate, but its mutate or change to a worst dot, also, i dont know why but in every generetion less dots spawn(or dots has exactly the same brain a dont mutate not even a litle), the mutation rate is in 100% but in every run there are less and less dots. Here screenshots of the first and 5th generation: https://i.sstatic.net/cGUJG.jpg
Also, if someone has some genetic algorithm in python to take as a model it would help.
Upvotes: 0
Views: 735
Reputation: 866
I did not try the project you mentioned. You may try PyGAD, a Python 3 library for building the genetic algorithm and training machine learning algorithms. It is open-source where you can find the code at GitHub.
It is simple to use which allows you to control the crossover, mutation, and parent selection operators in an easy way. You can also control many parameters of the genetic algorithm using PyGAD.
PyGAD also works with a user-defined fitness function so you can adapt it to a wide-range of problems.
After installing PyGAD (pip install pygad), here is a simple example to get started that tries to find the best values for W1, W2, and W3 that satisfies the following equation:
44 = 4xW_1 - 2xW_2 + 1.2xW_3
import pygad
import numpy
function_inputs = [4,-2, 1.2]
desired_output = 44
def fitness_func(solution, solution_idx):
output = numpy.sum(solution*function_inputs)
fitness = 1.0 / (numpy.abs(output - desired_output) + 0.000001)
return fitness
def on_generation(ga_instance):
print(ga_instance.population)
ga_instance = pygad.GA(num_generations=50,
num_parents_mating=2,
fitness_func=fitness_func,
num_genes=3,
sol_per_pop=5)
ga_instance.run()
ga_instance.plot_result()
solution, solution_fitness, _ = ga_instance.best_solution()
print("Parameters of the best solution : {solution}".format(solution=solution))
print("Fitness value of the best solution = {solution_fitness}".format(solution_fitness=solution_fitness))
Upvotes: 2