class Algoritmo: """ * @fc = frecuencia de corte * @tfiltro = tipo de filtro """ def __init__(self, fc, tfiltro): self.fc = fc self.tfiltro = tfiltro #Inicializo una señal S1 self.S1 = Signal() #Inicializo una señal S2 self.S2 = Signal() """ * Función que va a generar las señales con las que se va a calcular el valor fitness """ def generarSenales(self): #Genero la señal S1 self.S1.generate(self.fc - 200, amplitud, sinoidal=True) #Genero la señal S2 self.S2.generate(self.fc + 200, amplitud, sinoidal=True) """ * Función que crea la población """ def inicializarPoblacion(self): poblacion = [] #Voy a crear una población de 20 individuos for solucion in range(tamano_poblacion): individuo = Nodo() for x in range(tamano_individuos): individuo.solucion.append(random.uniform( -3, 3)) #Número al azar entre [-3, 3] #Para algunos coeficientes voy a modificar su valor a 1, porque sino tira error # y el auxiliar nos dio esta solución individuo.solucion[3] = 1 individuo.solucion[9] = 1 individuo.solucion[15] = 1 poblacion.append( individuo) #Agrego un nuevo individuo a la población #print('Individuo ', individuo.solucion) return poblacion #Retorno la población ya creada """ * Función que verifica si el algoritmo ya llegó a su fin """ def verificarCriterio(self, poblacion, generacion): #Si ya llegó al máximo de generaciones lo detengo if generacion >= maximo_generaciones: #Calculo una última vez el valor fitness de los individuos for individuo in poblacion: individuo.fitness = self.evaluarFitness(individuo.solucion) return True #Voy a ver a qué valores llega para ver el mejor fitness #return None # Veo si el 70% de la población tiene un valor fitness mayor a 'fitness_esperado' # Busco a los mayores porque mientras más alto es el valor fitness mejor es la solución contador = 0 for individuo in poblacion: #Actualizo el valor fitness del individuo individuo.fitness = self.evaluarFitness(individuo.solucion) contador += 1 if individuo.fitness > fitness_esperado else 0 return True if contador >= len(poblacion) * 0.7 else None """ * Función que evalúa qué tan buena es una solución, devuelve el valor fitness de la solución * * @solucion = arreglo con los coeficientes del filtro del cual se quiere obtener el valor fitness """ def evaluarFitness(self, solucion): #Desde el inicio generé la señal S1 #Filtro la señal S1 con los coeficientes de la solución que quiero evaluar #Inicializo el filtro 1 filtro1 = Filter(solucion) #Obtengo la señal de salida del filtro 1 T1 = filtro1.filter(self.S1) #Desde el principio generé la señal S2 #Filtro la señal S2 con los coeficientes de la solución que quiero evaluar #Inicializo el filtro 2 filtro2 = Filter(solucion) #Obtengo la señal de salida del filtro 2 T2 = filtro2.filter(self.S2) #Calcular la potencia media de T1 arreglo_absolutos1 = np.absolute(T1.y) arreglo_cuadrados1 = list( map(lambda elemento: cuadrado(elemento), arreglo_absolutos1)) sumatoria1 = sumatoria(arreglo_cuadrados1) P1 = (float(1) / float(2 * len(T1.y) - 1)) * float(sumatoria1) #print('sumatoria1:', sumatoria1) #print('P1: ', P1) #Calcular la potencia media de T2 arreglo_absolutos2 = np.absolute(T2.y) arreglo_cuadrados2 = list( map(lambda elemento: cuadrado(elemento), arreglo_absolutos2)) sumatoria2 = sumatoria(arreglo_cuadrados2) P2 = (float(1) / float(2 * len(T2.y) - 1)) * float(sumatoria2) #print('sumatoria2:', sumatoria2) #print('P2: ', P2) if self.tfiltro == "pb": #Si el filtro es pasa bajos fitness = P1 - P2 return fitness #De lo contrario el filtro es pasa altos fitness = P2 - P1 return fitness """ * Función que verifica si el algoritmo ya llegó a su fin """ def seleccionarPadres(self, poblacion): #Se elige a los mejores padres, quienes tengan un valor fitness más alto padres = sorted( poblacion, key=lambda item: item.fitness, reverse=True )[:tamano_padres_seleccionados] #Los ordena de mayor a menor return padres #Regreso solo a los padres seleccionados """ * Función que toma dos soluciones padres y las une para formar una nueva solución hijo """ def cruzar(self, padre1, padre2): hijo = [] for indice in xrange(0, len(padre1)): numero = random.uniform(0, 1) #Número al azar entre [0, 1] if numero > 0.5: #Se usa el valor de padre1 hijo.append(padre1[indice]) else: #Se usa el valor de padre2 hijo.append(padre2[indice]) return hijo #Retorno al hijo ya cruzado """ * Función que toma una solución y calcula si una posición muta o no """ def mutar(self, solucion): numero = random.uniform(-0.5, 0.5) #Número al azar entre [-0.5, 0.5] posicion = random.randint( 0, len(solucion) - 1) #Incluye ambos valores, por eso le quito uno al tamaño #En la mutación no se puede alterar el valor de los coeficientes en las posiciones 3, 9 y 15, estas siempre tienen valor 1 while posicion == 3 or posicion == 9 or posicion == 15: posicion = random.randint( 0, len(solucion) - 1) #Incluye ambos valores, por eso le quito uno al tamaño solucion[posicion] = solucion[posicion] + numero return solucion #Retorno la misma solución, solo que ahora mutó """ * Función que toma a los mejores padres y genera nuevos hijos * la cantidad de hijos generados está calculado de la siguiente manera: * nuevos_generados = tamano_poblacion - tamano_padres_seleccionados """ def emparejar(self, padres): nuevos_generados = tamano_poblacion - tamano_padres_seleccionados #Genero la cantidad de nuevos individuos dado por el valor de 'nuevos_generados' for x in range(nuevos_generados): hijo = Nodo() #hijo.solucion = cruzar(padres[random.randint(0, 4)].solucion, padres[random.randint(5, 9)].solucion) #Para cruzar voy a tomar [0 , (cantidadPadres / 2 - 1)] y [cantidadPadres / 2, cantidadPadres - 1] hijo.solucion = self.cruzar( padres[random.randint(0, len(padres) / 2 - 1)].solucion, padres[random.randint(len(padres) / 2, len(padres) - 1)].solucion) hijo.solucion = self.mutar(hijo.solucion) padres.append(hijo) #Agrego el nuevo hijo a la lista de padres return padres #Retorno la nueva población """ * Método para imprimir los datos de una población """ def imprimirPoblacion(self, poblacion): for individuo in poblacion: print('Fitness: ', individuo.fitness) """ * Método que ejecutará el algoritmo genético para obtener * los coeficientes del filtro """ def ejecutar(self): #np.seterr(over='raise') print("Algoritmo corriendo") generacion = 0 poblacion = self.inicializarPoblacion() fin = self.verificarCriterio(poblacion, generacion) while (fin == None): padres = self.seleccionarPadres(poblacion) poblacion = self.emparejar(padres) generacion += 1 #Lo pongo aquí porque en teoría ya se creó una nueva generación fin = self.verificarCriterio(poblacion, generacion) #generacion += 1 print('Cantidad de generaciones:', generacion) self.imprimirPoblacion(poblacion) #Obtengo la mejor solución, este va a ser el arreglo de coeficientes para el filtro coeficientes = sorted(poblacion, key=lambda item: item.fitness, reverse=True)[:1] #Los ordena de mayor a menor #Devuelvo el arreglo de coeficientes del filtro #coeficientes = [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0] return coeficientes[0].solucion
#!/usr/bin/env python # -*- coding: utf-8 -*- from Signal import Signal from Filter import Filter import matplotlib.pyplot as chart # Se inicializa la señal input = Signal() # Se genera una señal de 300 Hz # El primer parametro es la frecuencia # El segundo parametro es la amplitud # El tercer parametro indica si sera una funcion Seno o Coseno input.generate(300, 10, sinoidal=True) print(len(input.y)) # Coeficientes del filtro #individuo1 = [0.5999402, -0.5999402, 0, 1, -0.7265425, 0, 1, -2, 1, 1, -1.52169043, 0.6, 1, -2, 1, 1, -1.73631017, 0.82566455] #individuo1 = [-1.0680269827643445, -0.5713375209620128, -2.5686810550062686, 1, -1.507492099868706, 1.1328639399494786, -2.0312789297904277, 2.2819167893422474, 1.0782562420903563, 1, -2.406622049318159, 2.8184691203296985, 1.1009934668113424, 2.937768404798515, -1.2879034426159903, 1, 1.0779804598027694, 0.26138695967438075] individuo1 = [ 0.649111778514992, -2.561895750023369, -2.7064914522189003, 1, 0.42448483253776903, -0.7379594694212431, 2.3639384229526303, 0.7941637159051543, 0.12697375139804645, 1, 1.2652675834117865, 2.0737694481309585, 0.08310102365110283, 0.7794553652514429, -0.34982571481909996, 1, -1.0619745836793708, 1.9163873078077768 ]