From dd76061a22df6fcfe9d7c3ae413c53b7baa18062 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 2 Dec 2018 17:35:37 -0300 Subject: [PATCH] Added genetic algorithms and example implementations --- .DS_Store | Bin 0 -> 8196 bytes GeneticAlgorithm.py | 114 ++++++++++++++++++++ __pycache__/GeneticAlgorithm.cpython-36.pyc | Bin 0 -> 3124 bytes best_path_finder.py | 78 ++++++++++++++ bit_sequence_finder.py | 65 +++++++++++ secret_word_finder.py | 60 +++++++++++ 6 files changed, 317 insertions(+) create mode 100644 .DS_Store create mode 100644 GeneticAlgorithm.py create mode 100644 __pycache__/GeneticAlgorithm.cpython-36.pyc create mode 100644 best_path_finder.py create mode 100644 bit_sequence_finder.py create mode 100644 secret_word_finder.py diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..1083b108d2ea0c9cb43d6eb7dd23c92050a45e0d GIT binary patch literal 8196 zcmeHMU2GIp6h5adbgrdkS_|v|3o8wOwS@{T1w~l8rM9#PVO#pc&oa9+(23KTvNO92 zHceKdJ_$yi47_OkAwc32KKO$88-t1XP!llmL0^0{8cBRIo_p_XBb0q3O2XXa-tW#m z=iGben{Vdk>;eFG<&0+lA^@OJ<*3$B^MJzbyv`{V!N@#9qAMEr|-$%Q|W>?nYP_DdE8A;+Lq_HwcW;w%Bp$us}=S{4XdfE zVMmhVZXxOGe$MOCvnh3X(lX4no*lLfe|*q%cH3s&boONjbl=P#;?9GvYm*<4* zSxBjk3D@y;%Q3TJJ~_wXVaqYxLYJF!3{Ut6lZ*a--5;lUl&1Kx8{)p0!cuBvYO1}X zqb1hfv1Pg?Hr3hLM*YoOrl*;rXlr{89L=3Mcj4muAAES}^DjgcVDLqOdU-wDeo4JD z)EHjIPSbsG-!d+?mrqFcD$dVkkJV_seS7*-s+#l61E#I}R^IF;j=Yq*&?A=mGOn{f zYvzfa;f!nNCLFTVXLLK0BWH7$Z6~dlO>e|EPx-tz=DArvAsk06isfS|wSmX)oAfQ$ z@eZ0FJt$Dhw*TgNRkJ5=D$ZdCU&rej#niQ&BE zS!vrGbo2?c9$OfjS-d1tt1Z=*mrVDEC~A{3l1p1BbC!Qvtg&LH#ts{_^S!RYS25I& z6(%fAD>dy9wvOD9Nc9btWpnLwlNzo4O(Ca^uQRsJq{G$4LA$u-~zk{AHg-a4qwB! z@EzQO@8J&o48Owf@CW<}cj0fW#ztI>OE7{@VJmLHjkp!J;d8hhci|rF$G!L>Ch;&H z!4w|Ddiu2%DxK$+1B$y literal 0 HcmV?d00001 diff --git a/GeneticAlgorithm.py b/GeneticAlgorithm.py new file mode 100644 index 0000000..f128b36 --- /dev/null +++ b/GeneticAlgorithm.py @@ -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 + + + + + + + + + + \ No newline at end of file diff --git a/__pycache__/GeneticAlgorithm.cpython-36.pyc b/__pycache__/GeneticAlgorithm.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3081aa1d77d3a721b2aedaa79a60a6b94884913 GIT binary patch literal 3124 zcmaJ@-E!MR6y9C^SW#@paZ~z3N<*76xC0Fo7=})#6k5_U!=#;dpo0fSC|)(SW6RD; zF0MzuaxZuS-ho%zTdw*F+`xBMw&KPaq&a7gR=cY`-*?VgeO9UXXFsujd01iWZ?a;?o!Z2y|`)R29-Ozu7)mek z$+0tWz?v4shBy!xQj)ysNzq)9mb729rl0StxhhN2!*f}#NFQxQuF5jns;tN=+BLZ* zYiMh7UDnaA%QJEVZC!Hsa#q(KL~)e1Ti+0a(zK--xM?PNmoiwu@48NMR+-p~?_k}mg#X_&VA@slu(bal`l47=v} zX?q;$wdd_Lj*?_|7`JGUuEfLMexx2fr%fi>KS1+S*d4;IBx!$euMddLNPdXb?Ih|x zSF~g0ky;_;lUgNJhWd-CH8lV1?);cUD%n}$Z|8oL9AfDm`WA563g^J=oJ8uz;Fb1* zpdGiVddnG`ay5EPb1M1z zHohqNmta1yj{Ijx7tmavOksxOBoWExx%35Mic z)$pjR39>USV*DEVl6RmO_qgCy=(^bA7lkhb?D6F#(%zn5P)A`+b;VHkA&k+LlwbrY z_t~!-6XZ%qbdV)P91(R?o`K2t8jf~Q7!IO5STA9=qCM$4oNK>q%VF4^d zSjX*HX$kGD*W?1|^VGXoG56J!8{?~~ImD%|hA$%(9?Sz>5kWH^PxY57$k&jWzb^dU zVP{|% zg<}JK4)p;fdm@fD{)cazw@eY@c|03%2#AK0r{pGVy+Zl?y-8lf`Fk|}ZQ}I`%6Me5 z`8&K#D1nK73IKw{rwqNg1WPfg0K~<-qOLx{g9-6(7r^)&A&vx{vI((IEk%HZW6hq5 z2?e~JIa3ac0|r<~U=#Ai(S|rEErbA-0KL*u{Umt=_O)xyyU66VGGMrQ@K@sK_s7NQ zXW~JZ2BC`L^wYULc1!eL`F$-CuK9g$om_VHdCqw)*(}Mij34Th{2j;hSUKXx7iWZ z4YAIj1?e0**x z2=etBXXu9|4tr4$Xg>&gI5xXvmxJI4$4&mm1ZrN~E?`;p0jaa3D23HIQtPC)NYMdg zYPF&QrYHkUh$^B*(GC{^*kn2-w4zEy{w7;co}lzDZsAqDnrC}1Zl7*5davQ?QV_^~ qD+rVUkYLk3j^?zT;8!g%CDx2R?UUNOo%?%-zHO?kZIuC7+5Qi2w5I|9 literal 0 HcmV?d00001 diff --git a/best_path_finder.py b/best_path_finder.py new file mode 100644 index 0000000..0beec6d --- /dev/null +++ b/best_path_finder.py @@ -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() \ No newline at end of file diff --git a/bit_sequence_finder.py b/bit_sequence_finder.py new file mode 100644 index 0000000..77b0ffa --- /dev/null +++ b/bit_sequence_finder.py @@ -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() + + + + + + \ No newline at end of file diff --git a/secret_word_finder.py b/secret_word_finder.py new file mode 100644 index 0000000..334401b --- /dev/null +++ b/secret_word_finder.py @@ -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() + + + \ No newline at end of file