Untitled

mail@pastecode.io avatar
unknown
plain_text
6 months ago
9.4 kB
0
Indexable
Never
# Inicialización de variables
pCrossover = 0.75  # probabilidad de cruce
pMutación = 0.05  # probabilidad de mutación
poblacion = 10
ciclos = int(input("Ingresa el número de ciclos: "))
cantGenes = 30
cromosomas = []
cromosomasValor = []
cromosomasFuncObj = []
cromosomasFitness = []
nueva_generacion = []
maxFuncObj = 0
elitismo = True
torneo = True
cantCromosomasElite = 2
cantTorneo = 4
nombre_Excel = "TP1.xlsx"

# Definición de funciones

# Inicializa un archivo de Excel para almacenar los resultados
def inicializarExcel():
    global worksheet, workbook
    workbook = xlsxwriter.Workbook(nombre_Excel)
    worksheet = workbook.add_worksheet()
    worksheet.write(0, 0, "Ciclo")
    worksheet.write(0, 1, "Mínimo")
    worksheet.write(0, 2, "Máximo")
    worksheet.write(0, 3, "Promedio")
    worksheet.write(0, 4, "Cromosoma máximo decimal")
    worksheet.write(0, 5, "Cromosoma máximo")


# Cierra el archivo de Excel una vez que se han guardado todos los datos
def cerrarExcel():
    # Cerrar el archivo de Excel
    workbook.close()


# Guarda los resultados de cada ciclo en el archivo de Excel
def guardarDatos(i):
    cont = i + 1
    worksheet.write(cont, 0, i + 1)
    worksheet.write(cont, 1, min(cromosomasFuncObj))
    worksheet.write(cont, 2, maxFuncObj)
    worksheet.write(cont, 3, sum(cromosomasFuncObj) / len(cromosomasFuncObj))
    worksheet.write(cont, 4, max(cromosomasValor))
    worksheet.write(cont, 5, max(cromosomas))


# Selecciona los cromosomas con mayor aptitud para la siguiente generación y se agregan a la lista de cromosomas élite
def aplicarElitismo():
    global cromosomas, cromosomasFitness
    cromosomasElite = []
    cromos = cromosomasFitness[:]
    indice_maximo = cromosomasFitness.index(max(cromos))
    cromosomasElite.append(cromosomas[indice_maximo])
    cromos.pop(indice_maximo)
    indice_maximo = cromosomasFitness.index(max(cromos))
    cromosomasElite.append(cromosomas[indice_maximo])
    """ for i in range(cantCromosomasElite):
    #seleccionar cromosoma con mayor fitness
    
    print(f' tamaño cromo {len(cromos)}')
    print(f' tamaño indice {indice_maximo}')
    cromos.pop(indice_maximo )"""
    return cromosomasElite


# Realiza una selección basada en el método de la ruleta
def seleccionRuleta():
    parejas = []  # Lista que almacenará las dos parejas
    for i in range(2):
        numero_aleatorio = random.uniform(0, 1)
        probabilidad_acumulada = 0
        for j, probabilidad in enumerate(cromosomasFitness):
            probabilidad_acumulada += probabilidad
            if probabilidad_acumulada >= numero_aleatorio:
                parejas.append(
                    j
                )  # Agregamos el elemento seleccionado a la lista de parejas
                break
    return parejas  # Retornamos la lista con las dos parejas seleccionadas


# Realiza una selección basada en el método del torneo
def seleccionTorneo():
    parejas = []  # Lista que almacenará las dos parejas
    torneo = []
    for _ in range(2):
        for _ in range(cantTorneo):
            index = random.randrange(poblacion)  # seleccion de poblacion para eltorneo
            torneo.append(cromosomasFitness[index])
        seleccionado = max(torneo)  # ganador del torneo
        indice = cromosomasFitness.index(seleccionado)
        parejas.append(
            indice
        )  # Agregamos el elemento seleccionado a la lista de parejas
    return parejas


# Calcula la aptitud de un cromosoma dividiendo su valor de función objetivo entre la suma de todas las funciones objetivo de la población
def funcFitness(valorFuncObj):
    return valorFuncObj / sum(cromosomasFuncObj)


# Calcula la función objetivo para un valor dado
def funcObjetivo(x):
    return x / ((2**30) - 1)


def iniciarCromosomas():
    global maxFuncObj
    for i in range(0, poblacion):
        genes = (
            np.random.rand(cantGenes) < 0.5
        )  # genera una lista aleatoria de genes con true o false
        # Genera la cadena de genes binario
        genes_binario = ""
        for g in genes:
            genes_binario += str(int(g))
        # Agrega los genes a la lista de cromosomas, el valor entero y valor de la funcion objetivo
        cromosomas.append(genes_binario)
        cromosomasValor.append(int(genes_binario, 2))
        cromosomasFuncObj.append(funcObjetivo(cromosomasValor[i]))
    # Agrega los cromosomas a la lista de cromosomas fitness
    for x in cromosomasFuncObj:
        cromosomasFitness.append(funcFitness(x))
    maxFuncObj = max(cromosomasFuncObj)


# Genera una nueva generación de cromosomas a partir de dos cromosomas padre seleccionados
def nuevaGenracion(cromo1, cromo2):
    cromosoma1 = cromosomas[cromo1]
    cromosoma2 = cromosomas[cromo2]
    # crossover o cruce
    if (random.uniform(0, 1)) < pCrossover:
        rango = random.randrange(cantGenes)  # punto de corte de los genes
        aux1 = cromosoma1[:rango] + cromosoma2[rango:]
        aux2 = cromosoma2[:rango] + cromosoma1[rango:]
        cromosoma1 = aux1
        cromosoma2 = aux2
    # mutacion
    """ for i in range(cantGenes):
        if random.uniform(0, 1) < pMutación:
            cromosoma1 = cromosoma1[:i] + str(int(not int(cromosoma1[i]))) + cromosoma1[i+1:]
        if random.uniform(0, 1) < pMutación:
            cromosoma2 = cromosoma2[:i] + str(int(not int(cromosoma2[i]))) + cromosoma2[i+1:] """
    pm1 = random.uniform(0, 1)
    pm2 = random.uniform(0, 1)
    cromosoma1_lista = list(cromosoma1)
    cromosoma2_lista = list(cromosoma2)
    if pm1 < pMutación:
        gen = random.randrange(cantGenes)
        if cromosoma1[gen] == 0:
            cromosoma1_lista[gen] = 1  # Intercambio
        else:
            cromosoma1_lista[gen] = 0
    if pm2 < pMutación:
        gen = random.randrange(cantGenes)
        if cromosoma2[gen] == 0:
            cromosoma2_lista[gen] = 1  # Intercambio
        else:
            cromosoma2_lista[gen] = 0
    # print("".join(str(x) for x in cromosoma1_lista))
    cromosoma1 = "".join(str(x) for x in cromosoma1_lista)
    cromosoma2 = "".join(str(x) for x in cromosoma2_lista)
    # print("".join(str(x) for x in cromosoma2_lista))
    return cromosoma1, cromosoma2


# Calcula los valores de los cromosomas, las funciones objetivo y la aptitud para una nueva generación
def calcularValores(nueva_generacion):
    global cromosomasFitness, maxFuncObj
    i = 0
    cromosomasFitness = []
    for genes in nueva_generacion:
        cromosomasValor.append(int(genes, 2))
        cromosomasFuncObj.append(funcObjetivo(cromosomasValor[i]))
        i += 1
    for x in cromosomasFuncObj:
        cromosomasFitness.append(funcFitness(x))
    maxFuncObj = max(cromosomasFuncObj)


# Función principal que ejecuta el algoritmo genético
def iniciar():
    global cromosomas, cromosomasValor, cromosomasFuncObj
    # iniciar primera generacion
    iniciarCromosomas()
    # generar nuevas generaciones
    nueva_generacion = cromosomas.copy()
    for i in range(ciclos):
        cromosomas = nueva_generacion
        print("---------------------------------------------")
        print(f"GENERACION {i+1}")
        print(f"Cromosomas, {cromosomas}")
        print(f"valores, {cromosomasValor}")
        print(f"Funcion objetivo, {cromosomasFuncObj}")
        print(f"Funcion Fitness, {cromosomasFitness}")
        # valores a guardar
        guardarDatos(i)
        print(f"maximo cromosomas: {max(cromosomas)} ")
        print(f"maximo cromosomas decimal: {max(cromosomasValor)} ")
        print(f"Minimo funcObj, {min(cromosomasFuncObj)}")
        print(f"Maximo funcObj, {maxFuncObj}")
        print(f"Promedio funcObj, {sum(cromosomasFuncObj)/len(cromosomasFuncObj)}")
        nueva_generacion = []
        cromosomasValor = []
        cromosomasFuncObj = []
        if elitismo:
            cromosomasElite = aplicarElitismo()
            nueva_generacion.append(cromosomasElite[0])
            nueva_generacion.append(cromosomasElite[1])
            for i in range(int((poblacion - cantCromosomasElite) / 2)):
                # Seleccion de parejas
                if torneo:
                    parejas = seleccionTorneo()
                else:
                    parejas = seleccionRuleta()
                # Generar nueva generacion
                result = nuevaGenracion(parejas[0], parejas[1])
                nueva_generacion.append(result[0])
                nueva_generacion.append(result[1])
            calcularValores(nueva_generacion)
        else:
            for i in range(int(poblacion / 2)):
                # Seleccion de parejas
                if torneo:
                    parejas = seleccionTorneo()
                else:
                    parejas = seleccionRuleta()
                # print(parejas)
                # Generar nueva generacion
                result = nuevaGenracion(parejas[0], parejas[1])
                nueva_generacion.append(result[0])
                nueva_generacion.append(result[1])
            calcularValores(nueva_generacion)


inicializarExcel()
iniciar()
cerrarExcel()  # Se cierra el archivo de Excel y se guardan los datos