Marzo 17, 2026
Hay una clase de problemas que ninguna fórmula resuelve directamente. No porque no exista solución, sino porque el espacio de posibles soluciones es tan enorme que recorrerlo completo es computacionalmente imposible. Cuando me topé con ese tipo de problemas por primera vez, la pregunta natural fue: ¿cómo optimiza algo la naturaleza sin tener una ecuación? La respuesta a esa pregunta es, literalmente, la evolución. Y de ahí nacen los algoritmos genéticos.
Este post no es una clase de biología ni de matemáticas avanzadas. Es una guía práctica: cuándo los necesitas, qué necesitan para funcionar, cómo interpretar sus resultados y, sobre todo, dónde están sus límites reales. Porque conocer los límites de una herramienta es lo que te convierte en alguien que la usa bien.
Un algoritmo genético es una búsqueda dirigida por selección natural. En vez de explorar todo el espacio de soluciones o seguir un gradiente matemático, genera una población de soluciones candidatas, evalúa cuáles son mejores, las combina entre sí, introduce pequeñas variaciones aleatorias, y repite el proceso hasta converger en algo suficientemente bueno.
Esa última parte es importante: suficientemente bueno. Los algoritmos genéticos no garantizan el óptimo absoluto. Garantizan llegar a un resultado muy bueno en tiempo razonable. Y para la mayoría de problemas del mundo real, eso es exactamente lo que necesitas.
La pregunta correcta no es "¿puedo usar un GA aquí?" sino "¿existe una alternativa más directa?". Si la respuesta es sí, úsala. Los algoritmos genéticos brillan cuando esas alternativas no existen o son demasiado costosas.
Úsalos cuando el espacio de búsqueda es enorme y discreto. Encontrar el orden óptimo para visitar 30 puntos de entrega tiene más de 8 × 10³² combinaciones posibles. Ninguna computadora puede probarlas todas. El GA no las prueba todas, pero llega a una muy buena sin necesitarlo.
Úsalos cuando no existe una derivada que seguir. El gradient descent y sus variantes necesitan que la función objetivo sea diferenciable. Si tu evaluación involucra simulaciones, reglas de negocio, restricciones complejas o variables mixtas, no hay gradiente que calcular. El GA no lo necesita.
Úsalos cuando las variables interactúan de formas no lineales. Optimizar 15 parámetros de un sistema donde cada uno afecta a los demás de forma impredecible es exactamente el tipo de problema donde un GA supera a la búsqueda en grid o al ajuste manual.
Y también hay casos donde no deberías usarlos: cuando existe una solución analítica exacta, cuando el espacio de búsqueda es pequeño y la fuerza bruta es más simple, o cuando necesitas garantía matemática del resultado óptimo. Los GAs son heurísticas. Si tu aplicación requiere prueba formal de optimalidad, el camino es otro.
Logística y ruteo. El problema de ruteo de vehículos es NP-hard. Ningún algoritmo exacto lo resuelve en tiempo útil para más de 20-30 puntos. Un GA encuentra soluciones con 15-30% menos distancia que la asignación manual, en segundos o minutos de cómputo. Para una empresa con tres vehículos y 40 entregas diarias, eso se traduce en ahorro real de combustible y tiempo de repartidor todos los días.
Calibración de sistemas complejos. Parámetros de controladores, configuraciones de redes de manufactura, umbrales de clasificación en sistemas de señales biomédicas. Cuando tienes N parámetros que interactúan y no puedes modelar matemáticamente esas interacciones, el GA los optimiza conjuntamente sin que necesites entender cada relación causal.
Neuroevolución. En vez de entrenar una red neuronal con backpropagation, evolucionas su arquitectura completa: número de capas, tamaño, funciones de activación. Especialmente útil para redes que corren en hardware con restricciones duras de memoria o latencia, donde la arquitectura óptima no es intuitiva y el espacio de búsqueda es enorme.
Scheduling. Horarios de personal en hospitales, asignación de turnos, programación de operaciones en manufactura. Son problemas con restricciones duras y objetivos múltiples en conflicto: minimizar costo, maximizar cobertura, respetar descansos. El GA navega esas tensiones sin que tengas que resolverlas a mano.
Lo que me parece más elegante de los algoritmos genéticos es lo poco que necesitan de tu parte. No necesitas explicarle cómo llegar a la solución. Solo necesitas tres cosas:
Una codificación del problema. Cómo representas una solución como un individuo. Para ruteo es una permutación de puntos. Para parámetros numéricos es un vector de reales. Para configuraciones es un vector de bits o categóricos. Esta decisión define todo lo demás: qué operadores son válidos, qué cruces tienen sentido, qué mutaciones preservan la validez de la solución. Equivocarse aquí es el error más común.
Una función de fitness. La única fórmula que tú construyes. Toma un individuo y devuelve un número: qué tan buena es esa solución. Si optimizas logística es la distancia total. Si optimizas un clasificador es el accuracy. Si tienes múltiples objetivos en conflicto los combinas con pesos ponderados. Definir bien la función de fitness es, sin exagerar, el 80% del trabajo de diseño.
Datos o un simulador. El GA necesita evaluar miles de soluciones candidatas. Para eso necesita poder calcular el fitness de cada una, lo que requiere datos reales o un modelo que simule el comportamiento del sistema.
Una vez que tienes la codificación y el fitness, el GA opera con cinco mecanismos que se ejecutan en ciclo:
Inicialización. Genera N soluciones aleatorias válidas. Es la población de la generación 0, lo suficientemente diversa para cubrir el espacio de búsqueda sin sesgar la búsqueda desde el inicio.
Evaluación. Calcula el fitness de cada individuo. Es el paso más costoso computacionalmente porque involucra correr tu función de evaluación N veces por generación. Si tu función tarda un segundo, una población de 100 con 500 generaciones son 50,000 evaluaciones.
Selección. Elige qué individuos se reproducen. El método más robusto es el torneo: toma T individuos al azar, el de mayor fitness es un padre. Más grande el torneo, más presión selectiva, más rápida la convergencia, pero más riesgo de quedarse atrapado en óptimos locales.
Cruce. Combina dos padres para producir un hijo. Para vectores reales es interpolación. Para permutaciones, como rutas, se usa Order Crossover: copia un segmento de un padre y rellena el resto con el orden del segundo saltando los ya presentes. El operador correcto depende completamente de tu codificación.
Mutación. Pequeña perturbación aleatoria al hijo. Para reales es ruido gaussiano. Para permutaciones es intercambiar dos posiciones. Mantiene la diversidad y evita que toda la población colapse al mismo punto. Tasa de mutación demasiado alta: búsqueda aleatoria. Demasiado baja: convergencia prematura. Encontrar ese balance es parte del arte del diseño.
El output principal es el mejor individuo encontrado y su fitness. Pero los números secundarios son los que te dicen si ese resultado es confiable o si el algoritmo simplemente se quedó atascado.
La curva de convergencia grafica el mejor fitness por generación. Debe subir rápido al inicio y aplanarse. Si sigue subiendo linealmente después de muchas generaciones, necesitas más iteraciones. Si se aplana desde el inicio, tu población era demasiado pequeña o la tasa de mutación demasiado baja.
Fitness promedio vs mejor. Si el promedio de la población está muy cerca del mejor, toda la población convergió al mismo punto y el algoritmo dejó de explorar. Si está muy lejos, aún hay diversidad activa y el proceso sigue siendo productivo.
Diversidad. La desviación estándar de la población en el espacio de soluciones. Diversidad cercana a cero significa homogeneidad completa: todos los individuos son casi iguales. El GA terminó de aprender aunque sigas corriendo generaciones. Más generaciones a partir de ese punto no mejoran el resultado, solo consumen cómputo.
No existe un número fijo de generaciones correcto. El criterio de parada debe basarse en comportamiento, no en conteo arbitrario. Los tres más usados en producción:
Estancamiento. Para cuando el mejor fitness no mejora más de un umbral ε en las últimas K generaciones. K suele ser 50-100 dependiendo del problema. Es el criterio más común y más honesto.
Homogeneidad. Para cuando la diversidad cae por debajo de un mínimo. Ya no hay nada nuevo que explorar, seguir corriendo es gastar recursos.
Presupuesto de evaluaciones. Para cuando llevas N evaluaciones de fitness en total, independientemente del número de generaciones. Útil cuando cada evaluación tiene costo real: tiempo de simulación, llamadas a API externas, experimentos físicos.
Como referencia práctica: para problemas con 10-30 variables y población de 100 individuos, 200-500 generaciones suelen ser suficientes. Para 50 o más variables o problemas altamente multimodales, necesitas poblaciones de 500 o más y miles de generaciones.
Una confusión frecuente es pensar que un GA que está en producción corre continuamente. La realidad es que la mayoría de casos de uso siguen uno de dos patrones mucho más simples.
Una sola ejecución. El problema no cambia. Corres el GA, guardas los parámetros óptimos, los usas como configuración fija del sistema. Calibrar la arquitectura de una red neuronal para un dataset estático, optimizar el layout de una planta, diseñar la geometría de una pieza. Corres una vez, el resultado vive para siempre.
Re-optimización por drift. El problema evoluciona lentamente. Monitoreas una métrica de calidad en producción —accuracy, tasa de error, costo operativo— y cuando cae por encima de un umbral lanzas un nuevo ciclo. El punto clave aquí es usar warm start: inicializas la nueva población con la mejor solución del ciclo anterior más perturbaciones. Converge mucho más rápido porque ya sabes que estás cerca del óptimo y solo necesitas explorar el vecindario del cambio. Con warm start el costo del segundo ciclo en adelante se reduce dramáticamente.
Existe un tercer patrón donde el GA corre continuamente en background, pero el overhead de mantenimiento es alto y los casos donde realmente se justifica son pocos. Para la gran mayoría de sistemas reales, el patrón de re-optimización por drift con warm start cubre el mismo caso de uso con mucho menos complejidad operativa.
Esto es quizás lo más importante para pensar bien la arquitectura. Un GA resuelve el problema de optimización. No reemplaza los componentes que construyen el contexto del problema ni los que ejecutan la solución resultante.
En un sistema de ruteo, el GA decide el orden óptimo de visita. La matriz de costos que alimenta al GA la construye una API de ruteo con datos reales de calles y tráfico. La ruta navegable que se muestra al repartidor la genera esa misma API con la secuencia ya optimizada. Si hay un cierre o un accidente, el re-ruteo reactivo lo maneja un algoritmo más ligero que responde en milisegundos. El GA es el planificador, no el sistema completo.
Entender esa separación es lo que permite diseñar sistemas donde el GA es un módulo reemplazable, agnóstico al resto, que puede ser actualizado o sustituido sin tocar nada más. Esa modularidad no es solo buena arquitectura, es lo que hace que el sistema sea mantenible a largo plazo.
| Dimensión | Detalle |
|---|---|
| Tipo de problema | Optimización combinatoria, espacios enormes, sin derivada disponible |
| Inputs necesarios | Codificación del individuo + función de fitness + datos o simulador |
| Output | Mejor solución encontrada + curva de convergencia |
| Escala práctica | 10–80 variables con buen rendimiento; más requiere estrategias híbridas |
| Cuándo parar | Por estancamiento (K generaciones sin mejora) o diversidad mínima |
| Garantía | No garantiza óptimo global, sí solución muy buena en tiempo razonable |
| Patrón productivo | Una vez, o re-optimización por drift con warm start |
| No reemplaza | APIs de ruteo, algoritmos reactivos, modelos físicos, navegación |
Los algoritmos genéticos son una de esas herramientas que, cuando las entiendes bien, empiezas a ver los problemas donde encajan. No son magia ni son la solución a todo. Son una forma elegante de buscar en espacios donde la búsqueda directa es imposible, inspirada en el mecanismo más probado que existe: tres mil millones de años de evolución.
El visualizador interactivo que acompaña este post está construido con un GA real implementado desde cero en JavaScript: Order Crossover para cruce, swap mutation, selección por torneo y elitismo. Puedes seleccionar las paradas en el mapa de CDMX, ajustar los parámetros y ver cómo evoluciona la ruta generación a generación.
[ga-cdmx-map]Una charla sobre crear mientras se piensa.