Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import datetime
- import random as rnd
- import os
- # Inicializar parámetros de ejecución
- popSize = 50
- chromSize = 24
- probCrossover = 0.75
- probMutacionFinal = 0.4
- def clearScreen():
- # Limpia la terminal
- os.system('cls' if os.name == 'nt' else 'clear')
- def decision(probability):
- # Toma una decision aleatoria en base a una probabilidad
- return rnd.random() < probability
- class Chromosome(object):
- number_list = list(range(chromSize))
- def __init__(self, size, madre=None, padre=None, punto=None):
- # Constructor del cromosoma
- self.gen = []
- if madre == None:
- self.gen = random.sample(number_list, len(number_list))
- self.calculateValue()
- self.calculateScore()
- else:
- index = 0
- while(True):
- self.gen[index] = madre.gen[index]
- index = madre.index(padre.gen[index])
- if (index == 0):
- break
- for i in range(chromSize):
- if (self.gen[i] is None):
- self.gen[i] = padre.gen[i]
- def asString(self):
- # Devuelve un string en base al arreglo de genes
- chromStr = ""
- for g in self.gen:
- chromStr += str(g)
- return chromStr
- def calculateValue(self):
- # Calcula y guarda el valor entero decimal del cromosoma
- v = 0
- for g in range(len(self.gen)):
- v += self.gen[g] * (2 ** (chromSize - 1 - g))
- self.value = v
- def calculateScore(self):
- # Calcula y guarda el puntaje según la función objetivo
- self.score = ((self.value/((2**30)-1))**2)
- def calculateFitness(self, totalScore):
- # Calcula y guarda el valor fitness
- self.fitness = self.score/totalScore
- def mutate(self):
- # Muta un gen aleatorio del cromosoma
- punto = rnd.randint(0, chromSize-1)
- self.gen[punto] = 1 - self.gen[punto]
- self.calculateValue()
- self.calculateScore()
- class Population(object):
- def __init__(self, prevPopulation=None):
- # Constructor de la población
- self.chromosomes = []
- self.totalScore = 0
- # Crear población aleatoriamente
- if prevPopulation == None:
- for i in range(popSize):
- individuo = Chromosome(chromSize)
- self.addChromosome(individuo)
- # Crear población hija en base a la población previa
- else:
- # Aplicar elitismo
- self.addChromosome(prevPopulation.chromosomes[-2])
- self.addChromosome(prevPopulation.chromosomes[-1])
- for i in range(int(popSize/2)-2):
- padre = prevPopulation.selectWeightedChromosome()
- madre = prevPopulation.selectWeightedChromosome()
- # Aplicar crossover
- if decision(probCrossover):
- hijo1 = Chromosome(chromSize, madre, padre)
- hijo2 = Chromosome(chromSize, madre, padre)
- isNew = True
- else:
- hijo1 = padre
- hijo2 = madre
- isNew = False
- # Aplicar mutación
- if decision(probMutacionActual):
- hijo1.mutate()
- elif isNew:
- hijo1.calculateValue()
- hijo1.calculateScore()
- if decision(probMutacionActual):
- hijo2.mutate()
- elif isNew:
- hijo2.calculateValue()
- hijo2.calculateScore()
- # Agregar cromosomas hijos
- self.addChromosome(hijo1)
- self.addChromosome(hijo2)
- def addChromosome(self, c):
- # Agrega un cromosoma a la población
- self.chromosomes.append(c)
- def calculateTotalScore(self):
- # Calcula y guarda la suma de los puntajes de todos los cromosomas
- for c in self.chromosomes:
- self.totalScore += c.score
- def sortByFitness(self):
- # Calcula los valores fitness de cada cromosoma y ordena de menor a mayor
- for c in self.chromosomes:
- c.calculateFitness(self.totalScore)
- self.chromosomes.sort(key = lambda Chromosome: Chromosome.fitness)
- def selectWeightedChromosome(self):
- # Devuelve un cromosoma, teniendo mayor probabilidad dependiendo de su valor fitness
- # Obtener lista de los valores fitness de los cromosomas
- w = []
- for c in self.chromosomes:
- w.append(c.fitness)
- # Devolver cromosoma aleatorio
- return rnd.choices(
- population = self.chromosomes,
- weights = w
- )[0]
- def printStats(self):
- # Imprime en pantalla estadisticas de la población
- minimo = self.chromosomes[0].score
- maximo = self.chromosomes[-1].score # Indice -1 devuelve el último item
- promedio = self.totalScore / len(self.chromosomes)
- print("Máximo: ", maximo, "Mínimo: ", minimo, "Promedio: ", promedio)
- def printChrom(self):
- # Imprime en pantalla la lista de cromosomas
- for c in self.chromosomes:
- print(c.asString(), " f:", c.fitness)
- #################################
- # INICIO DEL PROGRAMA PRINCIPAL #
- #################################
- clearScreen()
- # Obtener número de iteraciones del usuario
- iteraciones = int(input("Ingrese cantidad de iteraciones a ejecutar: "))
- # Crear primera instancia de la población
- newPopulation = Population()
- for n in range(iteraciones):
- # Calcular y guardar puntajes y valores fitness de los cromosomas
- probMutacionActual=probMutacionFinal*n/iteraciones
- newPopulation.calculateTotalScore()
- newPopulation.sortByFitness()
- # Crear nueva población en base a la anterior
- prevPopulation = newPopulation
- newPopulation = Population(prevPopulation)
- resultChrom = prevPopulation.chromosomes[-1]
- # Imprimir resultado final en pantalla
- print("Resultado\n Cromosoma: {chrom}\n Valor entero: {value}\n Objetivo: {score}\n Fitness: {fitness}"
- .format(
- chrom = resultChrom.asString(),
- value = resultChrom.value,
- score = resultChrom.score,
- fitness = resultChrom.fitness))
- input("Presione una tecla para cerrar...")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement