108 lines
3.1 KiB
Python
108 lines
3.1 KiB
Python
import numpy as np
|
|
from matplotlib import pyplot as plt
|
|
|
|
qmin = -4
|
|
qmax = 4
|
|
GENE_LENGTH = 16
|
|
POPULATION_SIZE = 250
|
|
GENERATION_COUNT = 250
|
|
TOURNAMENT_SIZE = 5
|
|
x_values = np.linspace(-1, 1, 100)
|
|
|
|
mut_rate = 0.05 # Mutationsrate
|
|
|
|
def initGen():
|
|
return [np.random.randint(2, size=4 * GENE_LENGTH) for _ in range(POPULATION_SIZE)]
|
|
|
|
def gray_to_binary(gray_array):
|
|
binary_array = [gray_array[0]]
|
|
for i in range(1, len(gray_array)):
|
|
binary_array.append(binary_array[i - 1] ^ gray_array[i])
|
|
return binary_array
|
|
|
|
def binary_array_to_int(binary_array):
|
|
binary_string = ''.join(map(str, binary_array))
|
|
return int(binary_string, 2)
|
|
|
|
def grayToInt(gray_array):
|
|
return binary_array_to_int(gray_to_binary(gray_array))
|
|
|
|
def getCoefficents(gene):
|
|
params = []
|
|
for i in range(4):
|
|
dezimahl = grayToInt(gene[i * GENE_LENGTH: (i+1) * GENE_LENGTH])
|
|
q = qmin + (qmax - qmin) / (2**GENE_LENGTH - 1) * dezimahl
|
|
params.append(q)
|
|
|
|
return params
|
|
|
|
def goalFunction(x):
|
|
return np.exp(x)
|
|
|
|
def approxFunction(x, gen):
|
|
a, b, c, d = getCoefficents(gen)
|
|
return a*x**3 + b*x**2 + c*x + d
|
|
|
|
def fitnessFunction(gen):
|
|
squared_differences = (approxFunction(x_values, gen) - goalFunction(x_values)) ** 2
|
|
quadratic_error = np.mean(squared_differences)
|
|
return -quadratic_error
|
|
|
|
def tournament_selection(generation):
|
|
selected = [generation[np.random.randint(0, POPULATION_SIZE)] for _ in range(TOURNAMENT_SIZE)]
|
|
selected = sorted(selected, key=fitnessFunction, reverse=True)
|
|
return selected[0]
|
|
|
|
def crossover(gene1, gene2):
|
|
split = np.random.randint(1, len(gene1) - 1)
|
|
newGene1 = np.append(gene1[:split], gene2[split:])
|
|
newGene2 = np.append(gene2[:split], gene1[split:])
|
|
return newGene1, newGene2
|
|
|
|
def mutateL(gene):
|
|
if np.random.rand() < mut_rate:
|
|
bit = np.random.randint(0, GENE_LENGTH)
|
|
gene[bit] = 1 - gene[bit]
|
|
return gene
|
|
|
|
def mutate(gene):
|
|
for bit in range(len(gene)):
|
|
if np.random.rand() < mut_rate:
|
|
gene[bit] = 1 - gene[bit]
|
|
return gene
|
|
|
|
def main():
|
|
oldGen = initGen()
|
|
allTimeGene = oldGen[0]
|
|
alltimeFitness = -1000
|
|
|
|
for i in range(GENERATION_COUNT):
|
|
newGen = []
|
|
while len(newGen) < POPULATION_SIZE:
|
|
gene1 = tournament_selection(oldGen)
|
|
gene2 = tournament_selection(oldGen)
|
|
|
|
newgene1, newgene2 = crossover(gene1, gene2)
|
|
|
|
newGen.append(mutate(newgene1))
|
|
newGen.append(mutate(newgene2))
|
|
|
|
oldGen = np.array(newGen)
|
|
oldGen = sorted(oldGen, key=fitnessFunction, reverse=True)
|
|
|
|
if fitnessFunction(oldGen[0]) > alltimeFitness:
|
|
alltimeFitness = fitnessFunction(oldGen[0])
|
|
allTimeGene = oldGen[0]
|
|
print("Generation", i, "Best fitness:", alltimeFitness)
|
|
|
|
print("Final fitness:", alltimeFitness)
|
|
plt.plot(x_values, approxFunction(x_values, allTimeGene), label='Approximated f(x)')
|
|
plt.plot(x_values, goalFunction(x_values), label='Target g(x)', linestyle='dashed')
|
|
plt.title('Genetic Algorithm')
|
|
plt.xlabel('x')
|
|
plt.ylabel('y')
|
|
plt.legend()
|
|
plt.show()
|
|
|
|
if __name__ == "__main__":
|
|
main() |