In [48]:
import os
import numpy
import math
import matplotlib.pyplot as plt
import random
os.chdir('/home/andrey/Jupyter Notebooks/Andrey/Genom')
print(os.getcwd())
from GenomClass import Genom
In [44]:
gaussianParams = [[-1, 0.2], [1, 2], [3, 3]]
a = -10
b = 10
numPoints = 2000
random.seed()
In [5]:
def gaussian(X, x0, sigma):
res = ((1 / (math.sqrt(2 * math.pi) * sigma)) * numpy.exp(-((X - x0) ** 2) / (2 * (sigma) ** 2)))
return res
In [6]:
def gaussianComb(X: object, params: object) -> object:
res = numpy.zeros(X.size)
for par in params:
x0 = par[0]
sigma = par[1]
res += gaussian(X, x0, sigma)
return res
In [7]:
def calcCostFunction(X, y, params):
times = len(params)
m = X.size
resX = gaussianComb(X, params)
costVector = (resX - y) ** 2
J = (1 / (2 * m)) * numpy.sum(costVector)
return J
In [45]:
X = numpy.linspace(a, b, numPoints)
y = gaussianComb(X, gaussianParams)
plt.plot(X, y)
plt.show()
In [43]:
numberOfIndiv = 70
Population = []
for i in range(numberOfIndiv):
gene = Genom(3)
gene.calcFitnessFunction(X, y)
Population.append(gene)
In [47]:
def findNearest(popul, num):
indiv = popul[num]
population = []
population.extend(popul)
population.pop(num)
l = len(population)
indFF = indiv.getFitnessFunction()
popFF = numpy.zeros(l)
for i in range(l - 1):
popFF[i] = population[i].getFitnessFunction()
distances = numpy.abs(popFF - indFF)
minimum = distances.min()
for i in range(distances.size):
if distances[i] == minimum:
return population[i] # Переписать, говнокод
In [41]:
def selectParentsByInbriding(population):
N = len(population) - 1
parents = []
for i in range(numberOfIndiv):
fatherNum = random.randint(0, N)
father = population[fatherNum]
mother = findNearest(population, fatherNum)
pair = [father, mother]
parents.append(pair)
return parents
In [40]:
def newSelectParentsByInbriding(population):
N = len(population) - 1
parents = []
for i in range(numberOfIndiv // 2):
fatherNum = random.randint(0, N)
father = population[fatherNum]
mother = findNearest(population, fatherNum)
pair = [father, mother]
parents.append(pair)
return parents
In [39]:
def selectParents(population):
N = len(population) - 1
parents = []
for i in range(numberOfIndiv):
fatherNum = random.randint(0, N)
motherNum = random.randint(0, N)
father = population[fatherNum]
mother = population[motherNum]
pair = [father, mother]
parents.append(pair)
return parents
In [35]:
def newSelectParents(population):
N = len(population) - 1
parents = []
for i in range(numberOfIndiv // 2):
fatherNum = random.randint(0, N)
motherNum = random.randint(0, N)
father = population[fatherNum]
mother = population[motherNum]
pair = [father, mother]
parents.append(pair)
return parents
In [38]:
def crossingover(parents):
parentsList = list(map((lambda pair: list(map(lambda p: p.getParams(), pair))), parents)) #Составление списка генов родителей
numberOfGaussians = len(parentsList[0][0])
children = []
child = []
for pair in parentsList:
breakPoint = random.randint(1, (numberOfGaussians * 2) - 1) #Выбор точки разрыва хромосомы
if ((breakPoint % 2) == 0):
n = breakPoint // 2
child1 = [pair[0][i] for i in range(n)]
child2 = [pair[1][i] for i in range(n, numberOfGaussians)]
child = child1
child.extend(child2)
else:
n = (breakPoint - 1) // 2
child1 = [pair[0][i] for i in range(n)]
boundGaussian = [[pair[0][n][0], pair[1][n][1]]]
child2 = [pair[1][i] for i in range(n + 1, numberOfGaussians)]
child = child1
child.extend(boundGaussian)
child.extend(child2)
mutation = random.random() #Мутация
if (mutation >= 0.89):
num = random.randint(0, (numberOfGaussians * 2) - 1)
numOfGauss = num // 2
numOfElement = num % 2
child[numOfGauss][numOfElement] += random.uniform(-5, 5)
childObject = Genom(numberOfGaussians)
childObject.setParams(child)
children.append(childObject)
return children
In [32]:
def sortPop(population):
l = len(population)
sortList = [] #Временный list для сортировки вида [значение фитнесс функции, особь]
for i in range(l):
temp = [population[i].getFitnessFunction(), population[i]]
sortList.append(temp)
sortList.sort(key=lambda sL: sL[0])
sortedPopulation = list(map(lambda p: p[1], sortList))
return sortedPopulation
In [30]:
def makeNewPopulation(population, tX, tY):
for ind in population:
ind.calcFitnessFunction(tX, tY) #Вычисление фитнесс функции для каждей особи
sortedPopulation = sortPop(population) #Сортировка поппуляции по значению фитнесс функции
newPopulation = [sortedPopulation[i] for i in range(numberOfIndiv)]
return newPopulation
In [29]:
def new_makeNewPopulation(population, children, tX, tY):
newPopulation = []
for ind in population:
ind.calcFitnessFunction(tX, tY)
for ind in children:
ind.calcFitnessFunction(tX, tY)
sortedPopulation = sortPop(population)
newPopulation1 = [sortedPopulation[i] for i in range(numberOfIndiv // 2)]
newPopulation2 = [children[i] for i in range(numberOfIndiv // 2)]
newPopulation.extend(newPopulation1)
newPopulation.extend(newPopulation2)
return newPopulation
In [28]:
def geneticAlgorithm(pop, maxIters, tX, tY):
population = []
population.extend(pop)
bestList = []
for i in range(maxIters):
parents = selectParents(population)
childs = crossingover(parents)
all = []
all.extend(population)
all.extend(childs)
population = makeNewPopulation(all, tX, tY)
bestList.append(population[0].getFitnessFunction())
return [population[0].getParams(), bestList]
In [46]:
resList = geneticAlgorithm(Population, 2000, X, y)
params = resList[0]
bestList = resList[1]
yfit = gaussianComb(X, params)
print('Gaussian parametrs:')
print(params)
fig1 = plt.figure(figsize=(7, 7))
plt.title('Original and approximated function')
plt.plot(X, y, 'x', color='red')
plt.plot(X, yfit)
plt.show()
fig2 = plt.figure(figsize=(7, 7))
plt.title('Best fitness function')
plt.plot(bestList)
plt.show()
err = yfit - y
fig3 = plt.figure(figsize=(7, 7))
plt.title('Error')
plt.plot(X, err)
plt.show()
print('Mean error: ' + str(math.fabs(numpy.mean(err))))