<jupyter_start><jupyter_text>Optimización continua utilizando algoritmo genético Funciones a optimizar: -  Sphere Function -  Drop-Wave function -  Ackley function<jupyter_code>import numpy as np
import math
import matplotlib.pylab as plt<jupyter_output><empty_output><jupyter_text>Las 3 funciones se multiplican por un signo menos para convertir el problema de minimización en un problema de maximización.<jupyter_code>def sphere_function(x):
    # funcion en R^d
    d = x.size 
    fx = 0.0
    for i in range(d):
        fx += x[i]**2
        
    return -fx  
def dropWave_function(x):
    # funcion en R^2
    fx = -(1+math.cos(12.0*(x[0]**2+x[1]**2)**0.5))
    fx = fx/(0.5*(x[0]**2+x[1]**2)+2)
    return -fx
def ackley_function(x, a=20, b=0.2, c=2*math.pi):
    # funcion en R^d
    d = x.size 
    aux = 0.0
    for i in range(d):
        aux += math.cos(c*x[i])
        
    fx = -a*math.exp(-b*(-sphere_function(x)/d)**0.5)-math.exp(aux/d)
    fx += a + math.exp(1)
    
    return -fx<jupyter_output><empty_output><jupyter_text>Función de decodificaciónSe pasan como argumentos el individuo $a$, el número de bits $l_x$ para decodificar $x_i$, y los vectores $u=(u_1, \ldots, u_d)$, $v=(v_1, \ldots, v_d)$ que definen el dominio $[u_1, v_1]\times \dots \times [u_d, v_d]$ de la función `fitness` a maximizar. Devuelve el vector $x=(x_1,\ldots, x_d)\in [u_1, v_1]\times \dots \times [u_d, v_d]$ que representa el individuo $a$.<jupyter_code>def sigma(a, lx, u, v):
    aux = 0.0
    x = []
    
    for i in range(d):
        for j in range(lx):
            aux += a[(i+1)*lx-1-j]*2**j
        
        xi = u[i] +(v[i]-u[i])/(2**lx-1)*aux
        x.append(xi)
    
    return np.array(x)<jupyter_output><empty_output><jupyter_text>EvaluaciónFunción para evaluar la población $P$ de $N$ individuos de acuerdo a la función `fitness`.<jupyter_code>def evaluate(P, N, lx, u, v, fitness):
    ranking = []
    for i in range(N):
        x = sigma(P[i], lx, u, v)
        ranking.append(fitness(x))
        
    return ranking<jupyter_output><empty_output><jupyter_text>Operador de selección: Torneo binario`P` es la población de individuos de tamaño $N$. `ranking` es el arreglo del fitness de cada individuo ya precalculado anteriormente. `mu` es el número de ganadores del torneo a escoger.<jupyter_code>def selectionOperator(P, ranking, N, mu): 
    # 2*mu es el numero de torneos binarios, por lo que habra mu ganadores
    # regresa los indices de los individuos en P seleccionados
    
    randomIndex = np.random.choice(N, 2*mu, replace=True)
    winners = []
        
    k=0
    while 2*k+1 < 2*mu:
        i1 = randomIndex[2*k]
        i2 = randomIndex[2*k+1]
    
        i1_fitness = ranking[i1]
        i2_fitness = ranking[i2]

        if i1_fitness > i2_fitness:
            winners.append(i1)
        else:
            winners.append(i2)
        k += 1
            
    return winners<jupyter_output><empty_output><jupyter_text>Operador de cruzaCruza en dos puntos. `numVars` es igual a $d\cdot lx$.<jupyter_code>def crossoverOperator(S, numVars, mu):
    # S es la poblacion seleccionada de P a traves del operador de seleccion
    # mu es el numero de padres a cruzar, el tamaño de S
    # La cruza se hace en S mismo para optimizar
    
    randomIndex = np.random.choice(mu, mu, replace=False)
    
    i=0
    while 2*i+1<mu :
        i1 = randomIndex[2*i]
        i2 = randomIndex[2*i+1]
        
        # 2 puntos de crossover
        crossPoints = np.random.choice(range(1,numVars-1), 2, replace=False)
        crossPoints.sort()
        
        # Cruza de S[i1] con S[i2]
        offspring1 = S[i1]
        offspring2 = S[i2]
            
        for k in range(numVars):
            if k>=crossPoints[0] and k<=crossPoints[1]: # intercambio de bits de los individuos entre los puntos de cruza
                aux = offspring1[k]
                offspring1[k] = offspring2[k]
                offspring2[k] = aux
        
        i += 1<jupyter_output><empty_output><jupyter_text>Operador de mutaciónMutación uniforme<jupyter_code>def uniformMutationOperator(C, numVars, p):
    # C es el conjunto de individuos obtenidos al aplicar el operador de cruza
    # p es la probabilidad de mutacion
    # La mutacion dentro de C para optimizar
    
    for i in range(len(C)):
        for j in range(numVars):
            if np.random.uniform() <= p:
                C[i][j] = not C[i][j]<jupyter_output><empty_output><jupyter_text>Algoritmo GenéticoFunción para maximizar la función fitness $d$-dimensional definida en el compacto $[u_1, v_1]\times ... \times [u_d, v_d]$. Se pasan como argumentos la función `fitness`, la dimensión $d$, el tamaño $l_x$ para representar cada variable $x_i$, los vectores $u=(u_1, \ldots, u_d)$, $v=(v_1, \ldots, v_d)$ que definen el dominio, el tamaño de la población $N$ constante en cada generación, el porcentaje del elitismo `elite_percent`, y el número máximo de iteraciones `maxIter`.<jupyter_code>def maximize(fitness, d, lx, u, v, N=100, elite_percent=0.1, maxIter=100):
    
    mu = int((1-elite_percent)*N) # complemento del porcentaje de la elite
    numVariables = d*lx
    prob_mutation = 1.0/numVariables
    
    # Poblacion inicial de tamaño N con distribucion uniforme
    P = []
    for i in range(N):
        P.append(np.random.choice([0, 1], numVariables, replace=True))
    
    best_fitness = []
        
    for t in range(maxIter):
        # Evaluacion de P
        ranking = evaluate(P, N, lx, u, v, fitness)
        
        fit = [(ranking[i],i) for i in range(N)]
        fit.sort(reverse=True)
        elite = fit[:int(len(P)*elite_percent)]
        print('Generacion: ' + str(t) + ' - Mejor fitness de P: ' + str(elite[0][0]) + " - Indice " + str(elite[0][1]))
        
        best_fitness.append(elite[0][0])
        
        # Seleccion por torneo binario
        winners = selectionOperator(P, ranking, N, mu)

        P2 = []
        for i in range(len(winners)):
            P2.append(np.copy(P[winners[i]]))

        # Cruza
        crossoverOperator(P2, numVariables, mu)

        # Mutation
        uniformMutationOperator(P2, numVariables, prob_mutation)

        # Reemplazo 
        for i in range(len(elite)):
            P2.append(np.copy(P[elite[i][1]]))
            
        P = P2
        
    # Obtener el maximo fitness de la ultima generacion
        
    maxFit = float('-inf') 
    maxIndex = 0

    for i in range(N):
        aux = fitness(sigma(P[i], lx, u, v))
        if aux > maxFit:
            maxFit = aux
            maxIndex = i
    best_fitness.append(maxFit)
    
    print('Generacion: ' + str(maxIter) + ' - Mejor fitness de P: ' + str(maxFit) + " - Indice " + str(maxIndex))
        
    return sigma(P[maxIndex], lx, u, v), best_fitness<jupyter_output><empty_output><jupyter_text>Minimizando la sphere function<jupyter_code>d = 2
u = np.array([-5.12 for i in range(d)])
v = np.array([5.12 for i in range(d)])
lx = 50
maxIter = 100
x_star, best_fitness = maximize(sphere_function, d, lx, u, v, maxIter = maxIter)
x_star
plt.plot(range(maxIter+1), best_fitness)
plt.show()<jupyter_output><empty_output><jupyter_text>Minimizando la drop-wave function<jupyter_code>d = 2
u = np.array([-5.12 for i in range(d)])
v = np.array([5.12 for i in range(d)])
lx = 10
maxIter = 100
x_star, best_fitness = maximize(dropWave_function, d, lx, u, v, maxIter = maxIter)
x_star
plt.plot(range(maxIter+1), best_fitness)
plt.show()<jupyter_output><empty_output><jupyter_text>Minimizando la Ackley function<jupyter_code>d = 2
u = np.array([-5.12 for i in range(d)])
v = np.array([5.12 for i in range(d)])
lx = 10
maxIter = 100
x_star, best_fitness = maximize(ackley_function, d, lx, u, v, maxIter = maxIter)
x_star
plt.plot(range(maxIter+1), best_fitness)
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12517616912235746, 'fraction_numerical': 0.02062780269058296, 'mean_word_length': 2.8586258032624814, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '615357', 'license': 'MIT', 'n_tokens_mistral': 3002, 'n_tokens_neox': 2907, 'n_words': 757, 'path': 'GeneticAlgorithm/RealOptimization_GA.ipynb', 'repo_name': 'miguelruor/IA_code', 'size': '7805'}