-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added genetic algorithms and example implementations
- Loading branch information
Showing
6 changed files
with
317 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
@author: jcarraascootarola | ||
""" | ||
|
||
|
||
from random import randint | ||
from random import random | ||
from statistics import mean | ||
|
||
|
||
|
||
class GeneticAlgorithm: | ||
|
||
population =[] | ||
popFitness =[] | ||
bestFitness = [] | ||
averageFitness = [] | ||
generation = [] | ||
best = None | ||
numberOfGenerations = 0 | ||
|
||
def __init__(self,mutationRate, populationSize, fitnessFunction, numberOfGenes, geneValues, stopCondition): | ||
self.mutationRate = mutationRate | ||
self.populationSize = populationSize | ||
self.fitnessFunction = fitnessFunction | ||
self.numberOfGenes = numberOfGenes | ||
self.geneValues = geneValues | ||
self.stopCondition = stopCondition | ||
#k is the tournament selection size | ||
self.k = populationSize//2 | ||
|
||
|
||
|
||
|
||
def startAlgorithm(self): | ||
self.popCreation() | ||
while True: | ||
self.generation.append(self.numberOfGenerations) | ||
self.evaluateFitness() | ||
self.bestFitness.append(max(self.popFitness)) | ||
|
||
if self.best == None or self.bestFitness[-1] > self.fitnessFunction(self.best): | ||
self.best = self.population[self.popFitness.index(max(self.popFitness))] | ||
|
||
if self.stopCondition(self): | ||
|
||
break | ||
self.reproduction() | ||
self.numberOfGenerations+=1 | ||
|
||
def popCreation(self): | ||
for i in range(self.populationSize): | ||
self.population.append(self.individualCreation()) | ||
|
||
def individualCreation(self): | ||
individual=[] | ||
for i in range(self.numberOfGenes): | ||
individual.append(self.geneValues[randint(0,len(self.geneValues)-1)]) | ||
return individual | ||
|
||
def evaluateFitness(self): | ||
self.popFitness = [] | ||
for i in range(self.populationSize): | ||
self.popFitness.append(self.fitnessFunction(self.population[i])) | ||
self.averageFitness.append(mean(self.popFitness)) | ||
|
||
def selection(self): | ||
best = None | ||
bestIndex = 0 | ||
for i in range(self.k): | ||
index = randint(0, self.populationSize-1) | ||
if best == None or self.popFitness[index] > self.popFitness[bestIndex]: | ||
best = self.population[index] | ||
bestIndex = index | ||
return best | ||
|
||
def reproduction(self): | ||
newPopulation = [] | ||
for i in range(self.populationSize): | ||
parent1 = self.selection() | ||
parent2 = self.selection() | ||
baby = self.crossOver(parent1,parent2) | ||
baby = self.mutate(baby) | ||
newPopulation.append(baby) | ||
self.population = newPopulation | ||
|
||
def crossOver(self,parent1 ,parent2): | ||
mixingPoint = randint(0, len(parent1)-2) | ||
baby =[] | ||
for i in range(mixingPoint): | ||
baby.append(parent1[i]) | ||
for i in range(mixingPoint,len(parent1)): | ||
baby.append(parent2[i]) | ||
|
||
return baby | ||
|
||
def mutate(self,individual): | ||
mutatedIndividual=individual | ||
for i in range(len(individual)): | ||
if random() < self.mutationRate: | ||
mutatedIndividual[i] = self.geneValues[randint(0,len(self.geneValues)-1)] | ||
return mutatedIndividual | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Sun Dec 2 04:00:37 2018 | ||
@author: jcarraascootarola | ||
this is not meant to work properly but to show that some problems my need to adjust the genetic algorithm. | ||
In this case the regular implementation of the GA's mutation and crossover does not account for no repeated genes. | ||
""" | ||
from random import randint | ||
from GeneticAlgorithm import GeneticAlgorithm | ||
import time | ||
import matplotlib.pyplot as plt | ||
import math | ||
|
||
|
||
|
||
|
||
#hiperparameters | ||
mutationRate = 0.10 | ||
populationSize = 40 | ||
numberOfGenes = 5 | ||
|
||
#stopCondition Parameters | ||
maxGenerations=100 | ||
|
||
#problem parameters | ||
xSize=100 | ||
ySize=100 | ||
|
||
points = [] | ||
geneValues=[] | ||
|
||
def generatePoints(): | ||
for i in range(numberOfGenes): | ||
points.append([randint(0,ySize),randint(0,xSize)]) | ||
geneValues.append(i) | ||
|
||
|
||
def fitnessFunction(individual): | ||
traveledDistance = 0 | ||
for i in range(len(individual)-1): | ||
traveledDistance+=distance(points[individual[i]],points[i+1]) | ||
|
||
return 1/(traveledDistance+1) | ||
|
||
def distance(pointA,pointB): | ||
return math.sqrt((pointA[0]+pointB[0])**2 + (pointA[1]+pointB[1])**2 ) | ||
|
||
|
||
def stopCondition(algorithmInstance): | ||
|
||
if algorithmInstance.numberOfGenerations == maxGenerations: | ||
return True | ||
return False | ||
|
||
generatePoints () | ||
|
||
print("Entrenando, esto puede tomar un tiempo ...") | ||
start = time.time() | ||
ga = GeneticAlgorithm(mutationRate, populationSize, fitnessFunction, numberOfGenes, geneValues, stopCondition) | ||
ga.startAlgorithm() | ||
end = time.time() | ||
print("time elapsed: "+str(end - start)) | ||
print(ga.best) | ||
plt.figure(1) | ||
plt.plot(ga.generation, ga.bestFitness) | ||
plt.xlabel('Generation') | ||
plt.ylabel('Fittest individual fitness') | ||
plt.title("Best individual performance") | ||
|
||
plt.figure(2) | ||
plt.plot(ga.generation, ga.averageFitness) | ||
plt.xlabel('Generation') | ||
plt.ylabel('Population average fitness') | ||
plt.title("Average generation performance") | ||
plt.show() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
@author: jcarraascootarola | ||
""" | ||
|
||
|
||
import numpy as np | ||
from random import randint | ||
from random import random | ||
from GeneticAlgorithm import GeneticAlgorithm | ||
import time | ||
import matplotlib.pyplot as plt | ||
|
||
|
||
bitSequence="01011111100101011001010010101" | ||
geneValues=["0","1"] | ||
|
||
#hiperparameters | ||
mutationRate = 0.05 | ||
populationSize = 20 | ||
numberOfGenes = len(bitSequence) | ||
|
||
#stopCondition Parameters | ||
maxGenerations=100 | ||
|
||
def fitnessFunction(individual): | ||
total=0 | ||
for i in range(len(individual)): | ||
if bitSequence[i]==individual[i]: | ||
total+=1 | ||
return total | ||
|
||
|
||
def stopCondition(algorithmInstance): | ||
|
||
if algorithmInstance.numberOfGenerations == maxGenerations or fitnessFunction(algorithmInstance.best) == numberOfGenes: | ||
return True | ||
return False | ||
|
||
|
||
print("Entrenando, esto puede tomar un tiempo ...") | ||
start = time.time() | ||
ga = GeneticAlgorithm(mutationRate, populationSize, fitnessFunction, numberOfGenes, geneValues, stopCondition) | ||
ga.startAlgorithm() | ||
end = time.time() | ||
print("time elapsed: "+str(end - start)) | ||
plt.figure(1) | ||
plt.plot(ga.generation, ga.bestFitness) | ||
plt.xlabel('Generation') | ||
plt.ylabel('Fittest individual fitness') | ||
plt.title("Best individual performance") | ||
|
||
plt.figure(2) | ||
plt.plot(ga.generation, ga.averageFitness) | ||
plt.xlabel('Generation') | ||
plt.ylabel('Population average fitness') | ||
plt.title("Average generation performance") | ||
plt.show() | ||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
@author: jcarraascootarola | ||
""" | ||
|
||
from GeneticAlgorithm import GeneticAlgorithm | ||
import time | ||
import matplotlib.pyplot as plt | ||
|
||
|
||
wordToGuess="paralelepipedo" | ||
|
||
#hiperparameters | ||
mutationRate = 0.05 | ||
populationSize = 40 | ||
numberOfGenes = len(wordToGuess) | ||
|
||
#stopCondition Parameters | ||
maxGenerations=100 | ||
|
||
|
||
geneValues=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"," "] | ||
|
||
def fitnessFunction(individual): | ||
total=0 | ||
for i in range(len(individual)): | ||
if wordToGuess[i]==individual[i]: | ||
total+=1 | ||
return total | ||
|
||
|
||
def stopCondition(algorithmInstance): | ||
|
||
if algorithmInstance.numberOfGenerations == maxGenerations or fitnessFunction(algorithmInstance.best) == numberOfGenes: | ||
return True | ||
return False | ||
|
||
|
||
print("Entrenando, esto puede tomar un tiempo ...") | ||
start = time.time() | ||
ga = GeneticAlgorithm(mutationRate, populationSize, fitnessFunction, numberOfGenes, geneValues, stopCondition) | ||
ga.startAlgorithm() | ||
end = time.time() | ||
print("time elapsed: "+str(end - start)) | ||
plt.figure(1) | ||
plt.plot(ga.generation, ga.bestFitness) | ||
plt.xlabel('Generation') | ||
plt.ylabel('Fittest individual fitness') | ||
plt.title("Best individual performance") | ||
|
||
plt.figure(2) | ||
plt.plot(ga.generation, ga.averageFitness) | ||
plt.xlabel('Generation') | ||
plt.ylabel('Population average fitness') | ||
plt.title("Average generation performance") | ||
plt.show() | ||
|
||
|
||
|