def mejorVecino(posicionPG, sol, numVecinos, porcModificacion, datos): #,modificar): c = 0 #contador de vecinos bound = datos["bounds"] size = len(posicionPG) porcModificacion = porcModificacion / 100.0 n = size * porcModificacion #numero de cambios a cada vecino dependiendo del tamanio de la solucion n = int(n) ff = evaluar(sol, datos) fmin = ff smin = copy.copy(sol) for c in range(numVecinos): d = 0 #contador de cambios en cada vecino s1 = copy.copy(sol) while (d < n): x = random.randrange(size) #numero de dato ndato = posicionPG[x] if isinstance(s1[ndato], list): sdato = random.sample(bound[ndato], len(bound[ndato])) else: sdato = random.choice(bound[ndato]) s1[ndato] = sdato d = d + 1 ff1 = evaluar(s1, datos) if (c == 0 or ff1 < fmin): fmin = ff1 smin = copy.copy(s1) c = c + 1 return fmin, smin
def descensoColinaSimple(sol, datos, posProblema, iteraciones, porcentaje): bound = datos["bounds"] fact = evaluar(sol, datos) i = 0 s1 = copy.copy(sol) sol2 = s1 n = len(posProblema) n = porcentaje * n n = int(n) while i < iteraciones: d = 0 while (d < n): ndato = posProblema[random.randrange(len(posProblema))] #Se van a modificar los dias if isinstance(s1[ndato], list): sdato = random.sample(bound[ndato], len(bound[ndato])) else: sdato = random.choice(bound[ndato]) s1[ndato] = sdato d = d + 1 if evaluar(s1, datos) < fact: sol2 = s1 i = iteraciones i = i + 1 return sol2
def algoritmoGenetico(datos, numGeneraciones, tamPoblacion, Pcruza, probabilidadMutacion, porMutacion, porSeleccion): t1 = time() #GENERAR POBLACION INICIAL listaPoblacion = generaPoblacion(tamPoblacion, datos) sMax = evaluar(minimoP(listaPoblacion, datos), datos) # factibilidad mínima inicial contador = 0 #Para romper ciclo en caso de estancamiento #out = 0 #cambiosMinimos = 0 #cambiosGeneraciones = 0 #rangoCambios = 50 #(rango mínimo de cambios), si no se cumple se sale del ciclo. Entra cuando hay tres cambios positivos o negativos #anterior = 0 #GENERACIONES while (contador < numGeneraciones): # and cambiosMinimos != 1 and out < 3): #Seleccion (por Torneo) listaPadres = generaPadres(porSeleccion, tamPoblacion, listaPoblacion, datos) #Cruzamiento #N puntos Lineal (al azar) listaPoblacion = cruzarHijos(Pcruza, listaPadres, datos) #Mutacion listaNueva = [] for elem in listaPoblacion: listaNueva.append( mutar(probabilidadMutacion, porMutacion, elem, datos)) listaPoblacion = listaNueva fact = evaluar(minimoP(listaPoblacion, datos), datos) print "factibilidad: ", fact, " iteración: ", contador #VERIFICAR que no haya estancamiento en el algoritmo #if contador > 0: # cambiosGeneraciones = cambiosGeneraciones + abs(anterior - fact) #Ir sumando los cambios de 5 generaciones # if contador % 5 == 0:#Hacerlo cada ciertas iteraciones (cada 5 generaciones) # if cambiosGeneraciones != 0: # if abs(cambiosGeneraciones) < rangoCambios: # Si no hay mucho cambio en 5 generaciones salirse del ciclo porque ya no tiene caso buscar mas soluciones # cambiosMinimos = 1 # cambiosGeneraciones = 0 # Se reinicia el contador para volver a calcular otras 5 generaciones # out = 0 # else: # out = out+1 #es igual a 5 ciclos que no tienen cambios #anterior = fact contador = contador + 1 listMinimo = minimoP(listaPoblacion, datos) t2 = time() tiempo = t2 - t1 return tiempo, evaluar(listMinimo, datos), listMinimo, sMax #[tiempo,final,listMinimo]
def poblacionInicial(n, datos): contador = 0 solBest, datosFijosBest, datosPrioritariosBest = solucion(datos) while contador < n - 1: sBest, datosFIJOS, datosPRIORITARIOS = solucion(datos) if evaluar(sBest, datos) < evaluar(solBest, datos): solBest = sBest datosFijosBest = datosFIJOS datosPrioritariosBest = datosPRIORITARIOS contador = contador + 1 return solBest, datosFijosBest, datosPrioritariosBest
def busquedaTabu(datos,iteraciones,tamMemoria,vecinos,porcMod): t1 = time() #Para contabilizar el tiempo sol = solucion(datos) #Solución inicial S0 tempS = evaluar(sol,datos) #Factibilidad de la solución inicial c = 0 #Contador de iteraciones sBest = sol #Se asigna como sBest a la solución inicial #PARA Verificar si no hay cambios y romper el ciclo tabú #cambiosCiclos = 0 #anterior = 0 #out = 15 # parametro para verificar cada ciertas iteraciones si ya se estanco el algoritmo en una solucion #noHayCambios = 0 tabuList = [] while (c <= iteraciones): #and noHayCambios != 1): candidateList = [] sVecinos = SNeighborhood(sol,vecinos,porcMod,datos) for sCand in sVecinos: if sCand not in tabuList: candidateList.append(sCand) sCandidate = mejorCandidato(candidateList,datos) sol = sCandidate if (evaluar(sCandidate,datos) < evaluar(sBest,datos)): tabuList.append(sCandidate) sBest = sCandidate if len(tabuList) > tamMemoria: fin = len(tabuList) inicio = fin-tamMemoria tabuList = tabuList[inicio:fin] fact = evaluar(sBest,datos) print "factibilidad: ",fact, " iteración: ",c # Salirse si no hay cambios en un determinado número de iteraciones # if c > 0: # cambiosCiclos = cambiosCiclos + abs(anterior - fact) #Ir sumando los cambios de 5 generaciones # if c % out == 0:#Hacerlo cada ciertas iteraciones (cada 15 ) # if cambiosCiclos != 0: # if abs(cambiosCiclos) == 0: # Si no hay mucho cambio en 5 generaciones salirse del ciclo porque ya no tiene caso buscar mas soluciones # noHayCambios = 1 # cambiosCiclos = 0 # Se reinicia el contador para volver a calcular otras 5 generaciones # anterior = fact c = c+1 t2 = time() tiempo = t2 - t1 return tiempo,fact,sBest,tempS ################################################################################# #############################################################################################
def busquedaArmonica(datos, iteraciones, HMS, HMCR, BW, PAR): t1 = time() HM = generaPoblacion(HMS, datos) tempS = evaluar(minimoP(HM, datos), datos) c = 0 # contador de iteraciones #Para romper ciclo en caso de estancamiento #noHayCambios = 0 #anterior = 0 #cambiosCiclos = 0 #out = 15 # parametro para decidir si ya se estanco el algoritmo en una solucion while (c <= iteraciones): # and noHayCambios != 1): obtenerMemoria = random.random() if (obtenerMemoria < (HMCR / 100.00)): elem = getRandomHM(HM) #modificar la armonía en un porcentaje copia = elem[:] modificar(PAR, BW, copia, datos) else: copia = solucion(datos) #ESCOJER LA PEOR DE LA MEMORIA ARMÓNICA PARA SUSTITUIRLA CON EL NUEVO SI ES MEJOR [indice, maximo] = peorS(HM, datos) nuevo = evaluar(copia, datos) if nuevo < maximo: HM[indice] = copia vecMin = minimoP(HM, datos) fact = evaluar(vecMin, datos) print "fact: ", fact, " iteración: ", c #VERIFICAR que no haya estancamiento en el algoritmo #if c > 0: # cambiosCiclos = cambiosCiclos + abs(anterior - fact) #Ir sumando los cambios de 5 generaciones # if c % out == 0:#Hacerlo cada ciertas iteraciones (cada 15 ) # if cambiosCiclos != 0: # if abs(cambiosCiclos) == 0: # Si no hay mucho cambio en 5 generaciones salirse del ciclo porque ya no tiene caso buscar mas soluciones # noHayCambios = 1 # cambiosCiclos = 0 # Se reinicia el contador para volver a calcular otras 5 generaciones #anterior = fact c = c + 1 t2 = time() tiempo = t2 - t1 return tiempo, fact, vecMin, tempS
def peorS(lista, datos): maxLista = [] for i in range(len(lista)): maxLista.append(evaluar(lista[i], datos)) maximo = max(maxLista) for i in range(len(lista)): if (maxLista[i] == maximo): indice = i return [indice, maximo]
def minimoP(lista, datos): minLista = [] for i in range(len(lista)): minLista.append(evaluar(lista[i], datos)) minimo = min(minLista) for i in range(len(lista)): if (minLista[i] == minimo): indice = i return lista[indice]
def mejorVecino(solucion, numVecinos, porcModificacion, datos): c = 0 #contador de vecinos bound = datos["bounds"] mBound = datos["metabounds"] size = len(bound) n = size*porcModificacion #numero de cambios a cada vecino dependiendo del tamanio de la solucion ff= evaluar(solucion, datos) fmin = ff smin = copy.copy(solucion) posiciones = posicion(mBound) for c in range(numVecinos): d = 0 #contador de cambios en cada vecino s1=copy.copy(solucion) while (d <= n): d = d + 1 ndato = random.randrange(size) #numero de dato pos = busquedaBin(posiciones.values(),ndato) lenlgs = len(mBound[pos]["lgs"]) lgs = mBound[pos]["lgs"] sdato = random.choice(bound[posiciones[pos]]) #Se escoge el espacio t de manera aleatoria. s1[posiciones[pos]] = sdato if mBound[pos]["gpid"]: sdato = random.choice(bound[posiciones[pos]+1]) #Se escoge el espacio practica de manera aleatoria. s1[posiciones[pos]+1] for j in range(lenlgs): if(lgs[j]["hidx"] != -1): sdato = random.choice(bound[posiciones[pos]+lgs[j]["hidx"]]) #Se escoge la hora de manera aleatoria. s1[posiciones[pos]+lgs[j]["hidx"]] = sdato if(lgs[j]["pidx"] != -1): p = bound[posiciones[pos]+lgs[j]["pidx"]] sdato = random.sample(p,len(p)) s1[posiciones[pos]+lgs[j]["pidx"]] = sdato ff1 = evaluar(s1,datos) if (c == 0 or ff1 < fmin): fmin = ff1 smin = copy.copy(s1) c = c + 1 return fmin,smin
def recocidoSimulado(datos,iteraciones,tempI,tempMin,vecinos,cambiosPorc,reduccion): # PARAMETROS t1 = time() e = 2.7182818284 #numero de Euler sol = solucion(datos) #Solución inicial S0 S = evaluar(sol,datos) #factibilidad de la solucion inicial c = 0 #contador de iteraciones tempS = S #para retornar la factibilidad de la solución inicial #PARA romper ciclo cuando se repitan valores en cierta cantidad de iteraciones #out = 15 # parametro para verificar cada ciertas iteraciones si ya se estanco el algoritmo en una solucion #cambiosCiclos = 0 #anterior = 0 #noHayCambios = 0 while (c <= iteraciones and tempI >= tempMin):# and noHayCambios != 1): Sprima,solAux = mejorVecino(sol,vecinos,cambiosPorc, datos) delta = Sprima-S if (delta <= 0): S = Sprima sol = solAux else: exp = -delta/tempI n = e**exp a = random.uniform(0,1) if(a <= n): S = Sprima sol = solAux tempI = tempI*reduccion print "factibilidad: ",S, " iteración: ",c #PARA verificar que no se quede estancado el algoritmo y romper el ciclo # if c > 0: # cambiosCiclos = cambiosCiclos + abs(anterior - S) #Ir sumando los cambios de 5 generaciones # if c % out == 0:#Hacerlo cada ciertas iteraciones (cada 15 ) # if cambiosCiclos != 0: # if abs(cambiosCiclos) == 0: # Si no hay mucho cambio en 5 generaciones salirse del ciclo porque ya no tiene caso buscar mas soluciones # noHayCambios = 1 # cambiosCiclos = 0 # Se reinicia el contador para volver a calcular otras 5 generaciones # anterior = S c = c + 1 t2 = time() tiempo = t2 - t1 return tiempo,S,sol,tempS
def mejorCandidato(lista, datos): fEvalAux = 0 solAux = [] c = 0 best = [] for sol in lista: fEval = evaluar(sol, datos) if (c < 1): fEvalAux = fEval solAux = sol else: if fEvalAux > fEval: best = sol fEvalAux = fEval solAux = best else: best = solAux c = c + 1 return best
def busquedaArmonica(sol, datos, posicion, iteraciones, HMS, HMCR, BW, PAR): HM = generaPoblacion(HMS, sol) #HM.append(sol) #out = 15 # parametro para decidir si ya se estancó el algoritmo en una solucion c = 0 # contador de iteraciones #noHayCambios = 0 #anterior = 0 #cambiosCiclos = 0 while (c <= iteraciones): # and noHayCambios != 1): obtenerMemoria = random.random() if (obtenerMemoria < (HMCR / 100.00)): elem = getRandomHM(HM) #modificar la armonía en un porcentaje copia = elem[:] modificar(PAR, BW, copia, datos, posicion) else: copia = solucion(datos) #ESCOJER LA PEOR DE LA MEMORIA ARMÓNICA PARA SUSTITUIRLA CON EL NUEVO SI ES MEJOR [indice, maximo] = peorS(HM, datos) nuevo = evaluar(copia, datos) if nuevo < maximo: HM[indice] = copia vecMin = minimoP(HM, datos) #PARA romper ciclo en caso de que se quede estancado #fact = evaluar(vecMin,datos) #if c > 0: # cambiosCiclos = cambiosCiclos + abs(anterior - fact) #Ir sumando los cambios de 5 generaciones # if c % out == 0:#Hacerlo cada ciertas iteraciones (cada 15 ) # if cambiosCiclos != 0: # if abs(cambiosCiclos) == 0: # Si no hay mucho cambio en 5 generaciones salirse del ciclo porque ya no tiene caso buscar mas soluciones # noHayCambios = 1 # cambiosCiclos = 0 # Se reinicia el contador para volver a calcular otras 5 generaciones #anterior = fact c = c + 1 return vecMin
def recocidoSimulado(sol, posicion, datos, iteraciones, tempI, tempMin, vecinos, cambiosPorc, reduccion): S = evaluar(sol, datos) #factibilidad de la solucion inicial c = 0 # contador de iteraciones contadorPositivo = 0 while (c <= iteraciones and tempI >= tempMin): # and noHayCambios != 1): Sprima, solAux = mejorVecino(posicion, sol, vecinos, cambiosPorc, datos) delta = Sprima - S if (delta <= 0): S = Sprima sol = solAux contadorPositivo = 0 else: n = math.exp(-delta / tempI) a = random.random() contadorPositivo = contadorPositivo + 1 if (a <= n): S = Sprima sol = solAux tempI = tempI * reduccion c = c + 1 return sol
def hiperheuristica(datos, iteraciones, tamMemoria, vecinos, porcMod): t1 = time() #Se puede iniciar con la mejor solucion de 100 elementos aleatorios sBest, datosFIJOS, datosPRIORITARIOS = poblacionInicial( 100, datos) #Solución inicial S0 #se puede iniciar con un solo elemento aleatorio #sBest,datosFIJOS,datosPRIORITARIOS = solucion(datos) #Solución inicial S0 #sFinal = sBest #la solución incial datosPrioritarios = 0 #para ir contabilizando los datos prioritarios restantes #evalúa las colisiones de cada restricción y devuelve sus valores y las posiciones de colisiones posicion, listaFactibilidad = seleccionar(sBest, datos) c = 0 # contador de iteraciones tabuList = [] valorAuxRepeticiones = 0 contadorRepeticiones = 0 #5 % de valores repetidos para que se modifique a otro método #noRepetir = 20 #noRepetir = iteraciones*(noRepetir/100.0) #noRepetir = int(noRepetir) while (c < iteraciones): # and noHayCambios != 1): candidateList = [] #Genera vecinos sin tomar en cuenta los datos fijos sVecinos = SNeighborhood(sBest, vecinos, porcMod, datos, datosFIJOS) for sCand in sVecinos: if sCand not in tabuList: candidateList.append(sCand) sCandidate = mejorCandidato(candidateList, datos) #En esta parte se identifican los problemas en la solución posProblema, posProb2, metaH, fact, datosPrioritarios = verificarProblema( sCandidate, datos, listaFactibilidad, datosPRIORITARIOS, datosPrioritarios) #Para verificar que ya se hayan satisfecho los datos prioritarios para convertirlos en fijos if (datosPrioritarios == 1): datosFIJOS = datosFIJOS + list(datosPRIORITARIOS) datosPRIORITARIOS = [] datosPrioritarios = -1 datosFIJOS = set(datosFIJOS) posProblema = list(set(posProblema) - datosFIJOS) datosFIJOS = list(datosFIJOS) listaFactibilidad = fact #clases de teoria y practica no deben ser a la misma #hora, el mismo día (MODIFICAR DIA) if metaH == "local1": solNueva = descensoColinaSimple(sCandidate, datos, posProblema, 30, 40) #print "falta" #Las clases no deben impartirse fuera del horario de clases if metaH == "local2": solNueva = descensoColinaSimple(sCandidate, datos, posProblema, 30, 40) #print "falta" #Un profesor no puede estar en dos lugares distintos a la #misma hora, el mismo día (MODIFICAR HORA) if metaH == "local3": solNueva = descensoColina(sCandidate, datos, posProblema, 80, 40) #print "falta" #Dos o mas profesores o grupos no pueden estar en el mismo lugar #a la misma hora, el mismo día a menos que sea multiasignacion if metaH == "local4": datosFIJOS = set(datosFIJOS) posProb2 = list(set(posProb2) - datosFIJOS) datosFIJOS = list(datosFIJOS) solNueva = recocidoSimuladoModificado(sCandidate, datos, posProblema) solNueva = recocidoSimuladoModificado(solNueva, datos, posProb2) #Un mismo grupo no puede tener asignada otra clase, ya sea en el mismo # o diferente lugar a la misma hora, el mismo día. a menos que sean #clases de diferentes especialidades de ese grupo (MODIFICAR HORA) if metaH == "local5": #el algoritmo armónica necesita otros parámetros para mejorar la solución solNueva = sbusquedaArmonica(sCandidate, datos, posProblema) #solNueva = descensoColina(sCandidate,datos,posProblema,100,2) #Si un profesor da clases a la 8, no puede dar clases a la 1 (MODIFICAR HORA) if metaH == "local6": solNueva = descensoColinaSimple(sCandidate, datos, posProblema, 30, 40) #Un grupo no puede tomar clases obligatorias a la misma hora en la que un alumno de recursamiento toma clases junto a otro grupo #(MODIFICAR HORA) if metaH == "local7": solNueva = descensoColinaSimple(sCandidate, datos, posProblema, 30, 40) #Un grupo debe tener dos horas libres al día (MODIFICAR HORA) if metaH == "local8": solNueva = descensoColinaSimple(sCandidate, datos, posProblema, 30, 40) #Un espacio solo puede permitir 9 horas al día if metaH == "local9": solNueva = descensoColinaSimple(sCandidate, datos, posProblema, 50, 40) #Heuristica 1 (restricción débil) if metaH == "local10": solNueva = descensoColina(sCandidate, datos, posProblema, 30, 40) #Heurística 2 (restricción débil) if metaH == "local11": solNueva = descensoColina(sCandidate, datos, posProblema, 30, 40) if (evaluar(solNueva, datos) < evaluar(sBest, datos)): sBest = solNueva if len(tabuList) > tamMemoria: tabuList.pop(0) tabuList.append(solNueva) fact = evaluar(sBest, datos) print "factibilidad: ", fact, " iteración: ", c #PARA ROMPER CICLO cuando se estanca #if c > 0: # cambiosCiclos = cambiosCiclos + abs(anterior - fact) #Ir sumando los cambios de 5 generaciones # if c % out == 0:#Hacerlo cada ciertas iteraciones (cada 15 ) # if cambiosCiclos != 0: # if abs(cambiosCiclos) == 0: # Si no hay mucho cambio en 5 generaciones salirse del ciclo porque ya no tiene caso buscar mas soluciones # noHayCambios = 1 # cambiosCiclos = 0 # Se reinicia el contador para volver a calcular otras 5 generaciones #sol = sBest #anterior = fact #if(valorAuxRepeticiones == fact): # contadorRepeticiones = contadorRepeticiones + 1 #else: # contadorRepeticiones = 0 #if contadorRepeticiones >= noRepetir: # solucion2,datosFIJOS,datosPRIORITARIOS = solucion(datos) # datosPrioritarios = 0 # contadorRepeticiones = 0 # if evaluar(solucion2,datos) < evaluar(sBest,datos): # sFinal = solucion2 # sBest = solucion2 #valorAuxRepeticiones = fact #if evaluar(sBest,datos) < evaluar(sFinal,datos): # sFinal = sBest c = c + 1 t2 = time() tiempo = t2 - t1 #fact = evaluar(sFinal,datos) return tiempo, fact, sBest #,tempS