Algoritmos genéticos: población, cruce, mutación y selección en una mochila para la excursión
Genoma y aptitud, selección por torneo, cruce de un punto, mutación y elitismo, el teorema de los esquemas y la convergencia prematura — en el problema de la mochila con un óptimo conocido, de la tienda de campaña a FunSearch y AlphaEvolve.
Serie Fundamentos de IA Parte 27 de 52
- Mapa de la inteligencia artificial: qué es cada cosa y cómo encaja todo
- Breve historia de la inteligencia artificial: de Turing a los modelos de lenguaje
- Datos, modelo, entrenamiento, inferencia: los conceptos básicos en un solo ejemplo
- Cómo leer la notación matemática: símbolos, subíndices, sumatorios y cuantificadores
- Conjuntos y relaciones: las piezas con las que se construyen las definiciones en IA
- Funciones y aplicaciones: por qué todo modelo de IA es una función
- Lógica y demostraciones: las reglas con las que se razona en IA
- Grafos y árboles: la estructura sobre la que se apoyan la búsqueda y las redes neuronales
- Álgebra lineal para aprendizaje automático: vectores, matrices y por qué la IA sobre todo multiplica
- Derivadas, gradiente y regla de la cadena: cómo sabe un modelo en qué dirección aprender
- Descenso de gradiente: cómo aprende un modelo
- Qué es la probabilidad: del lanzamiento de un dado a los axiomas de Kolmogórov
- Probabilidad condicionada y teorema de Bayes: cómo cambiar una estimación cuando te enteras de algo nuevo
- Variable aleatoria y función de distribución: una sola función que lo dice todo sobre la distribución
- Función de densidad y función de probabilidad: por qué una variable continua tiene probabilidad cero en cada punto
- Esperanza, varianza y covarianza: dónde está una distribución, qué anchura tiene y qué se relaciona con qué
- Resumen de las distribuciones de probabilidad: Bernoulli, binomial, Poisson, uniforme, normal y exponencial
- Ley de los grandes números y teorema central del límite: por qué las medias se comportan de forma tan predecible
- Estadística y estimación de parámetros: máxima verosimilitud, MAP e intervalos de confianza
- Teoría de la información: entropía, entropía cruzada y divergencia KL, el origen de las funciones de pérdida
- Búsqueda en el espacio de estados: BFS, DFS, UCS y A* con animaciones
- Juegos y adversarios: minimax, poda alfa-beta y Monte Carlo tree search
- Satisfacción de restricciones: backtracking, propagación de restricciones y AC-3 con un sudoku y un mapa de regiones checas
- Lógica y sistemas basados en conocimiento: encadenamiento hacia delante y hacia atrás, resolución y sistemas expertos
- Planificación: STRIPS, el mundo de bloques, heurísticas a partir de la relajación y la planificación en los agentes de IA
- Búsqueda local y recocido simulado: un viajante por las capitales regionales checas
- Algoritmos genéticos: población, cruce, mutación y selección en una mochila para la excursión
- Estrategias evolutivas y programación genética: de la regla de un quinto a la ley de Kepler
- Optimización por colonia de hormigas: cómo un rastro de feromona encuentra un camino corto
- Optimización por enjambre de partículas: inercia, experiencia propia y experiencia del enjambre
- Neuroevolución: evolución de los pesos y la forma de las redes neuronales, y el algoritmo NEAT
- Conjuntos difusos y funciones de pertenencia: cómo escribir «algo cálido»
- Lógica difusa y probabilidad: por qué «algo cálido» no significa «probablemente cálido»
- Lógica difusa: t-normas, implicaciones y reglas SI–ENTONCES
- Control difuso: Mamdani y Sugeno, del ventilador al péndulo invertido sobre un carro
- Agrupamiento difuso: el algoritmo fuzzy c-means y los puntos entre clusters
- Sistemas neuro-difusos (ANFIS): reglas difusas que aprenden de los datos
- Cadenas de Markov: matriz de transición, distribución estacionaria y PageRank
- Modelos ocultos de Márkov: el algoritmo de Viterbi y el casino deshonesto
- Redes bayesianas: por qué está mojada la hierba y qué significa eso para el aspersor
- El filtro de Kalman: cómo estimar a partir de mediciones imprecisas dónde está un coche y a qué velocidad va
- Tipos de aprendizaje automático: supervisado, no supervisado, semisupervisado y más
- Prompts, contexto y RAG: cómo darle a un modelo la información correcta
- Autocodificadores variacionales (VAE): imágenes nuevas a partir de un espacio latente continuo
- Redes generativas adversarias (GAN): el falsificador contra el detective
- Modelos de difusión: cómo el ruido puro se convierte en una imagen
- Procesos de decisión de Markov: estados, acciones, recompensas y ecuaciones de Bellman
- Q-learning y DQN: aprender el valor de las acciones, de la tabla a la red neuronal
- Gradiente de la política y PPO: aprender directamente la política
- Cómo funciona un agente de IA: un modelo de lenguaje en un bucle con herramientas
- Programación con agentes de IA: encargo, pruebas y revisión
- Evaluación y seguridad de los sistemas de IA: cómo medir y cómo vigilar
Temario completo de la serie 52 de 83 temas publicados
- Cómo codificar una solución como genoma y cómo la selección, el cruce y la mutación mejoran toda una población.
- Por qué sin mutación la evolución converge prematuramente y para qué sirve el cruce.
- Dónde se usan hoy los algoritmos genéticos — incluso con un modelo de lenguaje en el papel de la mutación.
Conviene conocer antes: Búsqueda local y recocido simulado: un viajante por las capitales regionales checas
La naturaleza no tiene ingeniero y, sin embargo, ha producido el ojo, el ala y el cerebro. Le bastaron tres cosas: los individuos se diferencian entre sí, transmiten sus rasgos a su descendencia y los más aptos tienen más descendientes. En los años setenta, John Holland, de la Universidad de Michigan, mostró que esas mismas tres cosas funcionan también en un ordenador — como método general para buscar buenas soluciones a problemas que no sabemos resolver de forma ingeniosa. Un algoritmo genético no necesita gradiente ni fórmula; solo necesita saber decir cuál de dos soluciones es mejor.
Continúa la parte Búsqueda local y recocido simulado. El recocido mejoraba una sola solución; un algoritmo genético mejora toda una población de ellas a la vez.
1. El problema: una mochila para la excursión
Te preparas para una excursión de varios días. En casa tienes 24 cosas — tienda de campaña, saco de dormir, hornillo, cámara, libro… — y cada una pesa algo y sirve para algo. La mochila puede pesar como máximo 10 kg. ¿Qué llevar para que la utilidad sea lo mayor posible?
Definición — el problema de la mochila (0/1)
Se dan n objetos con pesos wi > 0 y utilidades ui > 0, y una capacidad W. Buscamos x ∈ {0, 1}n que maximice ∑i uixi sujeto a ∑i wixi ≤ W.
Cada objeto es una pregunta de «lo llevo o no lo llevo» — un uno o un cero. Hay 224 posibilidades, es decir, 16 777 216 mochilas. La estrategia voraz «primero lo más útil por kilo» suele funcionar, pero no garantiza el óptimo: un objeto pesado puede desplazar a tres ligeros que juntos valían más.
Con pesos enteros, el óptimo se puede calcular exactamente mediante programación dinámica — con los 24 objetos y una capacidad de 1 000 decagramos (1 dag = 10 g) son 24 000 pasos. La mejor mochila tiene 727 puntos de utilidad y pesa 9,9 kg; en casa se quedan la comida extra, la cámara, el libro, las sandalias y la crema solar. Gracias a ello veremos exactamente cuánto se acerca la evolución. Un algoritmo genético, sin embargo, resulta útil sobre todo donde no existe un método exacto así.
La programación dinámica rellena una tabla T[i][c] — la mejor utilidad que se puede alcanzar solo con los primeros i objetos cuando pueden pesar como máximo c. Cada casilla se calcula a partir de la fila de encima:
T[i][c] = max( T[i − 1][c] , T[i − 1][c − wi] + ui )
- T[i][c]
- la mejor utilidad de los primeros i objetos con capacidad c; la casilla T[n][W] es la respuesta a todo el problema
- T[i − 1][c]
- la opción «no llevo el objeto i-ésimo» — entonces lo mejor es lo que se podía componer con los objetos anteriores con la misma capacidad
- T[i − 1][c − wi]
- la opción «lo llevo» — el objeto ocupa wi, así que para el resto queda solo c − wi; el mejor aprovechamiento del resto ya está en la tabla (solo vale para c ≥ wi)
- ui
- la utilidad del objeto que hemos añadido en esa segunda opción
Ejemplo — la tabla para cuatro objetos y una capacidad de 50 dag
Frontal (10 dag, 25 puntos), navaja (10 dag, 18), hornillo (40 dag, 30) y esterilla (50 dag, 45). Todos los pesos son múltiplos de diez, así que bastan columnas de 10 en 10 dag:
| objetos | c = 0 | 10 | 20 | 30 | 40 | 50 |
|---|---|---|---|---|---|---|
| ninguno | 0 | 0 | 0 | 0 | 0 | 0 |
| + frontal | 0 | 25 | 25 | 25 | 25 | 25 |
| + navaja | 0 | 25 | 43 | 43 | 43 | 43 |
| + hornillo | 0 | 25 | 43 | 43 | 43 | 55 |
| + esterilla | 0 | 25 | 43 | 43 | 43 | 55 |
Navaja, c = 20: max(T[1][20], T[1][10] + 18) = max(25, 25 + 18) = 43
Hornillo, c = 40: max(T[2][40], T[2][0] + 30) = max(43, 0 + 30) = 43 — el hornillo no compensa
Hornillo, c = 50: max(T[2][50], T[2][10] + 30) = max(43, 25 + 30) = 55 — el hornillo y la frontal
Esterilla, c = 50: max(55, T[3][0] + 45) = max(55, 45) = 55
La estrategia voraz tomaría los objetos por utilidad por decagramo: la frontal (2,5 puntos/dag), la navaja (1,8), y después ni la esterilla (0,9) ni el hornillo (0,75) cabrían en los 30 dag restantes — solo 43 puntos. En el problema grande con 24 objetos, la estrategia voraz termina en 702 puntos: llena la mochila de cosas pequeñas y ya no queda sitio para la tienda (220 dag).
def batoh(w, u, W): # w, u: pesos y utilidades, W: capacidad
T = [0] * (W + 1) # la fila para «ningún objeto»
for i in range(len(w)):
for c in range(W, w[i] - 1, -1): # hacia atrás: T[c − w[i]] aún es de la fila i − 1
T[c] = max(T[c], T[c - w[i]] + u[i])
return T[W] # n · W pasos: 24 · 1000 = 24 000
2. Individuo, genoma y aptitud
Definición — genoma, población, aptitud
Un genoma (cromosoma) es una solución codificada — aquí una cadena x ∈ {0, 1}24, un bit (gen) por objeto. Una población es un multiconjunto P de genomas de tamaño fijo μ.
La aptitud (fitness) es una función F : {0, 1}n → ℝ que el algoritmo maximiza. Para la mochila
F(x) = ∑ uixi si la mochila cabe; si no, ∑ uixi − 3 · (∑ wixi − W).
Un individuo es una mochila concreta escrita como una fila de unos y ceros. La aptitud dice lo buena que es. No prohibimos una mochila sobrecargada, solo la penalizamos — tres puntos menos por cada decagramo de más. Así el algoritmo descubre el límite de capacidad poco a poco, y hasta una mochila sobrecargada puede tener genes que más tarde vengan bien.
F(x) = ∑ uixi − 3 · max(0, ∑ wixi − W)
- F(x)
- la aptitud de la mochila x — el único número con el que la selección compara individuos
- ∑ uixi
- la utilidad de los objetos empaquetados (xi = 1 cuenta el objeto, 0 lo omite) — lo que de verdad queremos maximizar
- 3
- el precio de un decagramo por encima del límite — es mayor que la mejor relación entre utilidad y peso (la frontal, 2,5 puntos/dag), así que añadir cualquier cosa a una mochila ya sobrecargada siempre reduce la aptitud
- max(0, ∑ wixi − W)
- la sobrecarga en decagramos; el máximo con cero garantiza que una mochila que cabe no reciba penalización y que una mochila más ligera no salga favorecida
Ejemplo — la aptitud de dos mochilas
Óptimo: utilidad 727, peso 990 dag ≤ 1 000 ⇒ F = 727 − 3 · 0 = 727
Óptimo + cámara (80 dag, 20 puntos): utilidad 747, peso 1 070 dag ⇒ F = 747 − 3 · 70 = 537
La cámara añade 20 puntos, pero la sobrecarga de 70 dag cuesta 210 — la selección aparta una mochila así de forma fiable.
3. Selección
Definición — selección por torneo y por ruleta
Selección por torneo de tamaño k: elige al azar k individuos de la población y devuelve el de mayor aptitud.
Selección por ruleta: elige el individuo x con probabilidad F(x) / ∑y ∈ P F(y) (requiere aptitud positiva).
La presión selectiva mide con qué fuerza la selección favorece a los individuos más aptos; en el torneo crece con k.
Un torneo: sacas tres mochilas al azar y la mejor de ellas se convierte en progenitora. Las mochilas mejores tienen así más hijos, pero incluso una mediocre tiene una oportunidad si se encuentra con otras más débiles. Si solo se reprodujeran las mejores de todas, la población degeneraría pronto en copias de un único individuo — y con ella desaparecería la diversidad de la que vive la evolución.
Lo fuerte que es un torneo se puede calcular exactamente. Nuestro programa sortea k individuos con reemplazo (el mismo individuo puede entrar dos veces en el torneo). Ordenemos la población del mejor (i = 1) al peor (i = μ):
P(gana el i-ésimo) = ( (μ − i + 1)k − (μ − i)k ) / μk
- P(gana el i-ésimo)
- la probabilidad de que sea precisamente el i-ésimo mejor individuo el que se convierta en progenitor
- (μ − i + 1)k
- el número de torneos en los que nadie es mejor que el i-ésimo — los k sorteos caen en él o en peores
- (μ − i)k
- de ellos restamos los torneos en los que el i-ésimo no está — esos los ganaría alguien peor; la diferencia son los torneos en los que el i-ésimo es el mejor presente
- μk
- el número de todos los torneos posibles (k sorteos, cada uno entre μ individuos) — al dividir obtenemos una probabilidad
Ejemplo — un torneo de tres entre 40 mochilas
μk = 403 = 64 000. En cada generación se seleccionan 38 progenitores (dos plazas las ocupan los individuos de élite):
el mejor: (403 − 393) / 64 000 = (64 000 − 59 319) / 64 000 ≈ 7,31 %, se esperan 38 · 0,0731 ≈ 2,78 selecciones
el 20.º mejor: (213 − 203) / 64 000 = (9 261 − 8 000) / 64 000 ≈ 1,97 %, se esperan ≈ 0,75 selecciones
el peor: (13 − 03) / 64 000 ≈ 0,0016 %, se esperan ≈ 0,0006 selecciones
Un individuo medio recibe 38/40 = 0,95 selecciones; el mejor, casi el triple. En general, en una población grande el mejor recibe aproximadamente k veces más que la media — por eso la presión selectiva crece con k.
4. Cruce y mutación
Definición — cruce de un punto
Para los progenitores a, b ∈ {0, 1}n elige al azar un punto c ∈ {1, …, n − 1}. Los descendientes son
(a1, …, ac, bc+1, …, bn) y (b1, …, bc, ac+1, …, an).
El cruce se realiza con probabilidad pc; si no, los descendientes son copias de los progenitores. Otras variantes son el cruce de dos puntos y el uniforme (cada gen de un progenitor al azar).
Cortas dos mochilas por el mismo sitio e intercambias los finales. El hijo recibe el principio de la lista de un progenitor y el final del otro. Si un progenitor resolvió bien el dormir y el otro la comida, el hijo tiene la oportunidad de heredar ambas cosas.
Definición — mutación de bits
Cada gen del descendiente se invierte (0 ↔ 1) de forma independiente con probabilidad pm, normalmente pm = 1/n — de media un gen por individuo.
De vez en cuando un hijo se diferencia de sus progenitores en un pequeño detalle: mete un objeto que no tenía ninguno de ellos o saca alguno. La mutación es la única fuente de genes completamente nuevos — el cruce solo sabe reorganizar lo que ya hay en la población.
Ejemplo — cuántos genes invierte la mutación
El número de genes invertidos sigue una distribución binomial: P(j genes) = C(n, j) · pmj · (1 − pm)n−j. Para n = 24 y pm = 1/24:
número esperado: n · pm = 24 · 1/24 = 1
ningún cambio: (23/24)24 ≈ 0,360 (para n grande se acerca a 1/e ≈ 0,368)
exactamente un gen: 24 · (1/24) · (23/24)23 ≈ 0,376
Así que aproximadamente un tercio de los descendientes queda sin cambios, un tercio se diferencia en un gen y el resto en dos o más.
Los progenitores son las dos mejores mochilas de la población inicial (423 y 398 puntos), y el corte está después del duodécimo objeto. Ninguno de los descendientes es mejor que el mejor de los progenitores — tienen 403 y 418 puntos. El cruce no garantiza una mejora; solo ofrece combinaciones nuevas, y la selección decide luego cuáles sobreviven. En el primer descendiente, la mutación metió un filtro de agua (15 dag, 32 puntos), y de golpe tiene 435 puntos — más que ambos progenitores.
Ejemplo — recálculo del cruce de la figura
La utilidad se suma gen a gen, así que basta con sumar por separado la utilidad del principio (objetos 1–12) y del final (objetos 13–24):
progenitor 1: 310 + 113 = 423, progenitor 2: 305 + 93 = 398
descendiente 1 = principio del progenitor 1 + final del progenitor 2: 310 + 93 = 403
descendiente 2 = principio del progenitor 2 + final del progenitor 1: 305 + 113 = 418
la mutación mete el filtro de agua: 403 + 32 = 435
El progenitor 1 es mejor en ambas mitades (310 > 305 y 113 > 93), así que con este corte ningún descendiente puede superarlo — el cruce no tiene con qué componer un todo mejor. La mejora solo llegó con la mutación.
5. El algoritmo completo
Algoritmo — algoritmo genético
- Crea una población inicial aleatoria de μ individuos y evalúalos.
- Copia sin cambios los e mejores individuos en la nueva generación (elitismo).
- Mientras la nueva generación no tenga μ individuos: selecciona dos progenitores, crúzalos con probabilidad pc, muta los descendientes y añádelos.
- Evalúa la nueva generación y continúa con el paso 2 hasta agotar el número de generaciones.
Generación tras generación: los dos mejores sobreviven directamente y el resto de plazas lo ocupan los hijos de progenitores aptos, un poco reordenados y un poco alterados. El elitismo garantiza que la mejor mochila encontrada nunca se pierda.
import random
def evoluce(zdatnost, n, velikost=40, generaci=60, p_krizeni=0.9, elita=2):
pop = [[int(random.random() < 0.3) for _ in range(n)] for _ in range(velikost)]
for _ in range(generaci):
pop.sort(key=zdatnost, reverse=True)
dalsi = [g[:] for g in pop[:elita]] # elitismo
while len(dalsi) < velikost:
a, b = turnaj(pop, zdatnost), turnaj(pop, zdatnost)
if random.random() < p_krizeni:
bod = random.randrange(1, n)
a, b = a[:bod] + b[bod:], b[:bod] + a[bod:]
dalsi += [mutuj(a), mutuj(b)]
pop = dalsi[:velikost]
return max(pop, key=zdatnost)
def turnaj(pop, zdatnost, k=3):
return max(random.choices(pop, k=k), key=zdatnost) # k sorteos con reemplazo
def mutuj(g):
return [1 - x if random.random() < 1 / len(g) else x for x in g]
El coste del algoritmo lo medimos por el número de evaluaciones de la aptitud — en problemas reales (simulaciones, mediciones) es el paso más caro. Se evalúa la población inicial y después cada generación: μ + G · μ = 40 + 60 · 40 = 2 440 evaluaciones para μ = 40 individuos y G = 60 generaciones. Los individuos de élite se vuelven a evaluar aunque no hayan cambiado; un programa más listo recordaría su aptitud.
6. La evolución de la mochila
Pongamos en marcha el algoritmo: 40 mochilas, 60 generaciones, torneo de tres, cruce con probabilidad 0,9, mutación 1/24 y dos individuos de élite. La figura muestra la población en las generaciones 0, 5, 15, 30 y 60 — cada fila es una mochila, cada columna un objeto y, arriba, el óptimo para comparar:
Al principio la población es variada y las mochilas están más bien medio vacías: cada objeto entró en ellas con probabilidad 0,3, así que pesan unos cuatro kilos (el peso esperado es 0,3 · ∑ wi = 0,3 · 12,75 kg ≈ 3,8 kg). La mejor tiene 423 puntos y la media, 231. Tras cinco generaciones, 36 de las 40 mochilas llevan la tienda, 35 la botella de agua, y la mejor mochila tiene 634 puntos. Hacia la decimoquinta generación la población choca con la capacidad — 12 mochilas están sobrecargadas — y empieza a aprender qué sacrificar: la comida extra y las sandalias casi han desaparecido, pero la cámara aún la llevan 39 mochilas. El algoritmo encuentra el óptimo, 727 puntos, por primera vez en la generación 26; en la generación 30 la cámara ya solo queda en una mochila. Sin embargo, la población nunca se funde en una sola solución — la mutación sigue probando pequeñas desviaciones.
Para ello el algoritmo evaluó 2 440 mochilas — no llega a dos centésimas por ciento de las 16 777 216 posibilidades. Una búsqueda aleatoria con el mismo número de intentos no encontró el óptimo ni una sola vez en cien repeticiones y terminó de media en 574 puntos.
Ejemplo — por qué la búsqueda aleatoria no encuentra el óptimo
Una mochila aleatoria toma cada objeto de forma independiente con probabilidad 0,3. El óptimo contiene 19 objetos y deja fuera 5, así que
P(mochila aleatoria = óptimo) = 0,319 · 0,75 ≈ 1,16 · 10−10 · 0,168 ≈ 1,95 · 10−11
número esperado de aciertos en 2 440 intentos: 2 440 · 1,95 · 10−11 ≈ 4,8 · 10−8
Incluso si se sorteara de manera uniforme (cada objeto con probabilidad 1/2), la probabilidad sería de una entre 16 777 216 por intento. Un algoritmo genético no saca el óptimo de una vez — lo va componiendo pieza a pieza a partir de mochilas que ya son buenas.
7. Para qué sirve el cruce y para qué la mutación
La línea naranja del gráfico es la misma ejecución con la mutación desactivada. Tras once generaciones se atasca en 573 puntos y ya no se mueve. El porqué lo muestra una comparación de cien ejecuciones con semillas distintas:
| Variante | Encontró el óptimo | Utilidad media |
|---|---|---|
| Selección + cruce + mutación | 88 de 100 | 726,6 |
| Selección + mutación (sin cruce) | 70 de 100 | 725,0 |
| Selección + cruce (sin mutación) | 0 de 100 | 596,8 |
| Búsqueda aleatoria, mismos intentos | 0 de 100 | 573,5 |
Sin mutación, la población pierde diversidad: cuando un gen no está en ningún individuo, el cruce no puede producirlo, y además la selección desplaza rápidamente todo menos lo mejor. A esto se le llama convergencia prematura. Sin cruce el algoritmo funciona — en el fondo es una población de escaladores con selección —, pero es más lento. El cruce ayuda a juntar buenas piezas que surgieron en individuos distintos.
Teorema — el teorema de los esquemas de Holland
Un esquema H es un patrón sobre {0, 1, ∗}, donde ∗ significa «cualquier cosa»; su orden o(H) es el número de posiciones fijas y su longitud de definición δ(H) la distancia entre la primera y la última posición fija. Para m(H, t) individuos que encajan en H en la generación t y selección por ruleta se cumple
E[m(H, t + 1)] ≥ m(H, t) · F(H) / F̄ · [1 − pc · δ(H) / (n − 1) − o(H) · pm],
donde F(H) es la aptitud media de los individuos del esquema y F̄ la media de la población.
Un esquema es un «bloque de construcción», por ejemplo «llevo la tienda y el saco de dormir, lo demás da igual». El teorema dice que los bloques cortos con aptitud superior a la media se propagan por la población — y de forma exponencialmente rápida, porque en cada generación su número se multiplica aproximadamente por el cociente F(H) / F̄. Cortos, porque el cruce los corta con menos frecuencia. El teorema es solo una cota inferior, y sobre lo bien que funciona el algoritmo se sigue discutiendo hoy.
E[m(H, t + 1)] ≥ m(H, t) · F(H) / F̄ · [1 − pc · δ(H) / (n − 1) − o(H) · pm]
- m(H, t)
- cuántos individuos llevan ahora el bloque — la siguiente generación parte de ellos, por eso se multiplica por esto
- F(H) / F̄
- cuánto más aptos que la media son los portadores del esquema — la ruleta les da proporcionalmente más descendientes; por encima de 1 el esquema se multiplica, por debajo de 1 se extingue
- pc · δ(H) / (n − 1)
- la probabilidad de que el cruce corte el esquema: el cruce ocurre con pc y el punto de corte cae entre las posiciones fijas con probabilidad δ/(n − 1) — por eso perjudican los esquemas largos
- o(H) · pm
- la probabilidad (acotada por arriba) de que la mutación invierta alguna de las o(H) posiciones fijas — por eso perjudican los esquemas de orden alto
Ejemplo — un esquema corto y uno largo en la mochila
El corchete para los ajustes de nuestra ejecución (pc = 0,9, n = 24, pm = 1/24). Ambos esquemas tienen orden 2:
«la tienda y el saco de dormir» (genes 1 y 2, δ = 1): 1 − 0,9 · 1/23 − 2/24 ≈ 1 − 0,039 − 0,083 = 0,878
«la tienda y calcetines de repuesto» (genes 1 y 24, δ = 23): 1 − 0,9 · 23/23 − 2/24 ≈ 1 − 0,9 − 0,083 = 0,017
Al esquema corto le basta con que sus portadores sean un 14 % más aptos que la media (1/0,878 ≈ 1,14) para que, según el teorema, ya se propague. El esquema largo tendría que ser sesenta veces más apto — el teorema no promete prácticamente nada sobre él. Nuestro algoritmo usa torneo, no ruleta, así que para él solo vale el corchete; los dos primeros factores se calcularían de otra manera.
8. Los algoritmos genéticos en la práctica
- Diseño de formas. La antena de los satélites ST5 de la NASA (lanzados en 2006) fue diseñada por un algoritmo evolutivo: un alambre extrañamente retorcido que a ningún ingeniero se le habría ocurrido, pero que cumplió los requisitos al menos tan bien como una antena diseñada a mano (y en experimentos posteriores, incluso mejor).
- Horarios y logística. Horarios, turnos de trabajo o la distribución de un almacén — problemas con muchas restricciones en los que la aptitud se puede calcular, pero un algoritmo exacto tardaría una eternidad.
- Aprendizaje automático. La evolución ajusta los hiperparámetros de los modelos y, en la neuroevolución, a la que el temario dedica una parte propia, incluso los pesos y las arquitecturas de las redes neuronales.
- Evolución con modelos de lenguaje. Sistemas como FunSearch (2023) y AlphaEvolve (2025), de Google DeepMind, mantienen una población de programas y usan como mutación un modelo de lenguaje que modifica un programa. La selección corre a cargo de una evaluación automática. Así se han encontrado nuevas construcciones matemáticas y algoritmos más rápidos.
9. Resumen
- Un algoritmo genético mejora toda una población de soluciones: seleccionando a los aptos, con el cruce y con la mutación.
- La aptitud es lo único que necesita saber del problema; las restricciones incumplidas se pueden tratar con una penalización.
- La selección por torneo mantiene la presión selectiva y el elitismo no deja que se pierda la mejor solución.
- En una mochila con 16,7 millones de posibilidades encontró el óptimo en 88 de 100 ejecuciones tras evaluar 2 440 mochilas; la búsqueda aleatoria con el mismo presupuesto, ni una sola vez.
- La mutación aporta diversidad — sin ella la población converge prematuramente. El cruce junta buenos bloques de construcción y acelera la evolución.
¿Quieres probarlo tú? Pide a un agente de IA que escriba un algoritmo genético para tu propia mochila de excursión — y luego prueba a desactivar la mutación, agrandar el torneo o reducir la población, y observa qué pasa con la diversidad.
¿Lo ves de otra manera? Escribe a support@coden-app.com.