def mutation(n, individual: Individual): randx = random.randint(0, n - 3) randy = random.randint(0, n - 1) # deepcopy para evitar cambiar las referencias al original auxInd = deepcopy(individual) auxValue = abs(individual.getIndividual()[randx][randy]) - 1 auxInd.individual[randx][randy] = auxValue return auxInd
def generateNeighbourhood(n, individual: Individual, refFitness): Neighbourhood = list() eval = (-math.inf, -math.inf) index = None for i in range(len(individual.getIndividual())): for j in range(len(individual.getIndividual()[i])): #deepcopy para evitar cambiar las referencias al original auxInd = deepcopy(individual) #Copiamos el original auxValue = abs(individual.getIndividual()[i] [j]) - 1 #Cambiamos el valor que genera un vecino auxInd.individual[i][ j] = auxValue #Guadamos el cambio en el vecino #Añadimos el vecino Neighbourhood.append(auxInd) #Añadimos el vecino a la lista #Conforme calculamos los vecinos, los vamos evaluando auxeval = None auxeval = fitness(n, auxInd.getIndividual()) #Evaluamos el vecino ''' SE PUEDE COMENTAR PARA QUITAR ESTA CONDICION''' #Si el individuo generado tiene mejor coste que refFitness, lo devolvemos, no seguimos if auxeval[1] > refFitness[1]: eval = auxeval index = (i * n) + j #para calcular el indice del mejor individuo return (Neighbourhood, index, eval) '''''' if auxeval[1] > eval[1]: eval = auxeval index = (i * n) + j #para calcular el indice del mejor individuo elif auxeval[1] == eval[1] and auxeval[0] > auxeval[0]: eval = auxeval index = (i * n) + j #Si ninguna configuración tiene solución, como eval es -inf, se devolverá la primera encontrada, # y se buscará otra configuración en le algoritmo alterando el individuo evaluado return (Neighbourhood, index, eval)
def generatePopulation(n, popSize): ''' n tamaño de problema popSize tamaño de la población ''' population = list() for i in range(popSize): population.append(Individual(n, None)) return population
def crossover1(parent1: Individual, parent2: Individual): # Creamos los dos individuos Hijo c1 = [[int for _ in range(len(parent1.getIndividual()[0]))] for _ in range(len(parent1.getIndividual()))] c2 = [[int for _ in range(len(parent1.getIndividual()[0]))] for _ in range(len(parent1.getIndividual()))] #Tamaño del individuo indSize = len(parent1.getIndividual()) * len(parent1.getIndividual()[0]) #Máscara: mask = [[random.randint(0, 1) for _ in range(indSize)] for _ in range(indSize - 2)] # Cruce for i in range(len(parent1.getIndividual())): for j in range(len(parent1.getIndividual()[0])): if (mask[i][j]): c1[i][j] = parent2.getIndividual()[i][j] c2[i][j] = parent1.getIndividual()[i][j] else: c1[i][j] = parent1.getIndividual()[i][j] c2[i][j] = parent2.getIndividual()[i][j] c1 = Individual(None, c1) c2 = Individual(None, c2) return c1, c2
def crossover2(parent1: Individual, parent2: Individual): # Creamos los dos individuos Hijo c1 = [[int for _ in range(len(parent1.getIndividual()[0]))] for _ in range(len(parent1.getIndividual()))] c2 = [[int for _ in range(len(parent1.getIndividual()[0]))] for _ in range(len(parent1.getIndividual()))] #Tamaño del individuo indSize = len(parent1.getIndividual()) * len(parent1.getIndividual()[0]) #Obtener punto de cruce crossoverPoint = random.randint(0, indSize - 1) # Cruce for i in range(len(parent1.getIndividual())): for j in range(len(parent1.getIndividual()[0])): if (i * len(parent1.getIndividual()[0]) + j > crossoverPoint): c1[i][j] = parent2.getIndividual()[i][j] c2[i][j] = parent1.getIndividual()[i][j] else: c1[i][j] = parent1.getIndividual()[i][j] c2[i][j] = parent2.getIndividual()[i][j] c1 = Individual(None, c1) c2 = Individual(None, c2) return c1, c2
def crossover3(parent1: Individual, parent2: Individual): #Creamos los dos individuos Hijo c1 = [[int for _ in range(len(parent1.getIndividual()[0]))] for _ in range(len(parent1.getIndividual()))] c2 = [[int for _ in range(len(parent1.getIndividual()[0]))] for _ in range(len(parent1.getIndividual()))] #Tamaño de un individuo indSize = len(parent1.getIndividual()) * len(parent1.getIndividual()[0]) #Obtener los puntos de cruce crossoverPoints = list() crossoverPoints.append(random.randint(0, indSize - 1)) x = None while (x == crossoverPoints[0] or x == None): x = random.randint(0, indSize - 1) crossoverPoints.append(x) crossoverPoints.sort() #Cruce for i in range(len(parent1.getIndividual())): for j in range(len(parent1.getIndividual()[0])): if (i * len(parent1.getIndividual()[0]) + j >= crossoverPoints[0]): if (i * len(parent1.getIndividual()[0]) + j <= crossoverPoints[1]): c1[i][j] = parent2.getIndividual()[i][j] c2[i][j] = parent1.getIndividual()[i][j] else: c1[i][j] = parent1.getIndividual()[i][j] c2[i][j] = parent2.getIndividual()[i][j] else: c1[i][j] = parent1.getIndividual()[i][j] c2[i][j] = parent2.getIndividual()[i][j] c1 = Individual(None, c1) c2 = Individual(None, c2) return c1, c2
def HillClimbing(n, seed, it): ''' n: tamaño del problema seed: semilla aleatoria it: número de iteraciones ''' random.seed(seed) #El mejor individuo encontrado bestIndividual = None bestFitness = (-math.inf, -math.inf) #Inicializamos otras variables necesarias iteration = 0 bestNeighbIndex = None actualFitness = None #Generamos una configuración aleatoria de muros actualIndividual = Individual(n, None) actualFitness = fitness(n, actualIndividual.getIndividual()) print("Individuo inicial: ") actualIndividual.__str__() #Iteramos while iteration < it: #Introducimos no determinismo, generando individuos aleatorios con probabilidad 0.x (variable) if (random.random() < 0.2): #print("Aleatorio") bestNeighb = Individual(n, None) randomNeighbFit = fitness(n, bestNeighb.getIndividual()) newFitness = randomNeighbFit else: #Generamos los vecinos (solo hasta que encontremos el mejor, # o todos si no hay ninguno mejor que el actual) result = generateNeighbourhood(n, actualIndividual, actualFitness) neighbourhood = result[0] #Vecinos bestNeighbIndex = result[1] #El mejor encontrado bestNeighb = neighbourhood[bestNeighbIndex] newFitness = result[2] #Fitness del mejor encontrado #Si no obtenemos solución de los vecinos, alteramos el actual if bestNeighbIndex == None: print("Sin solucion en el vecindario") actualIndividual = mutation(n, bestIndividual) #print("IT: " + iteration.__str__() + " ACTUAL [N.Exp: " + actualFitness[0].__str__() + ", Coste: " + actualFitness[1].__str__() + "] [N.Exp: " + newFitness[0].__str__() + ", Coste: " + newFitness[1].__str__() + "]") iteration += 1 if (newFitness[1] > actualFitness[1] or (newFitness[1] == actualFitness[1] and newFitness[0] > actualFitness[0])): actualIndividual = bestNeighb actualFitness = newFitness #De esta manera no tenemos que reevaluar el fitness del actual, solamente si lo alteramos abajo elif ( newFitness[1] != -1 or (newFitness[1] == -1 and actualFitness[1] == -1) ): #APLICAMOS ILS, PERO SIN TENER EN CUENTA INDIVIDUOS SIN SOLUCIÓN ALEATORIOS #print("Alteración individuo") #Alteramos el mejor individuo en vez de el actual actualIndividual = mutation(n, actualIndividual) actualFitness = fitness(n, actualIndividual.getIndividual()) #Actualizamos el mejor individuo hasta ahora if (actualFitness[1] > bestFitness[1]): bestFitness = actualFitness bestIndividual = actualIndividual print("IT: " + iteration.__str__() + ", Mejor Solución [N.Exp: " + bestFitness[0].__str__() + ", Coste: " + bestFitness[1].__str__() + "]") print("Mejor Individuo: ") bestIndividual.__str__() print("Nodos Expandidos: " + bestFitness[0].__str__() + " Coste de la solución: " + bestFitness[1].__str__()) return bestFitness