Resolver problemas NP-hard con herramientas reales, no reinventándolas
La tentación de implementar tu propio algoritmo de optimización es fuerte y casi siempre equivocada. Cuándo apoyarse en herramientas especializadas es la decisión de ingeniería correcta.
Hay un momento predecible en cualquier proyecto que involucra optimización de rutas, asignación de recursos o programación de tareas: alguien en el equipo sugiere implementar el algoritmo. Dijkstra, A*, un solver de programación lineal escrito a mano. La intención es buena, es un problema interesante, y resolverlo se siente como ingeniería de verdad. El resultado, casi siempre, es tiempo de desarrollo invertido en reconstruir algo que ya existe, probado en producción durante años, con un nivel de optimización que un desarrollador no va a alcanzar en el tiempo disponible de un proyecto comercial.
Por qué la intuición es engañosa aquí
El problema de asignar decenas de paradas a un conjunto de vehículos con restricciones de capacidad y ventanas de tiempo no es una versión más grande del camino más corto entre dos puntos. Es un problema de una clase de complejidad distinta (NP-hard), donde el espacio de soluciones crece de forma combinatoria y no existe un algoritmo conocido que garantice la solución óptima en tiempo razonable a cualquier escala. Los algoritmos clásicos de grafos, como Dijkstra, resuelven un problema relacionado pero fundamentalmente más simple: la ruta más corta entre dos nodos, no la asignación óptima de múltiples paradas a múltiples vehículos con restricciones.
Confundir estos dos problemas es el origen del error: se implementa correctamente el algoritmo equivocado.
La decisión de ingeniería real
La pregunta que hay que hacerse no es "¿puedo implementar este algoritmo?", casi cualquier ingeniero con formación en estructuras de datos puede. La pregunta es "¿el valor de negocio está en el algoritmo de optimización en sí, o en integrarlo correctamente al resto del sistema?" Para la inmensa mayoría de productos, logística, agendamiento, asignación de recursos, la respuesta es la segunda. El negocio no compite en tener el mejor solver de ruteo del mundo, compite en tener el producto completo que usa ese solver correctamente: datos limpios de entrada, restricciones bien modeladas, resultados bien presentados, y un sistema que reacciona a cambios en tiempo real.
Herramientas especializadas y maduras para este tipo de problemas, solvers de ruteo de vehículos, motores de cálculo de distancias sobre mapas reales, librerías de programación por restricciones, han recibido años de optimización específica para casos que un desarrollador individual no puede replicar en el tiempo de un sprint. Apoyarse en ellas no es una renuncia a la ingeniería, es dirigir el esfuerzo de ingeniería hacia donde el negocio realmente lo necesita: la integración, el modelado de restricciones específicas del dominio, y la experiencia del usuario final.
El riesgo del lado contrario
Esto no es un argumento para nunca escribir algoritmos propios. Hay casos legítimos, restricciones muy específicas del negocio que ninguna herramienta genérica modela bien, volúmenes que no justifican la complejidad operativa de una herramienta externa, o restricciones de licenciamiento, donde construir algo propio, más simple, es la decisión correcta. El error no es escribir un algoritmo propio, es hacerlo por default, sin comparar explícitamente el costo de construir y mantener contra el costo de integrar una herramienta ya resuelta.
La lección
La ingeniería madura en estos casos no se mide por la capacidad de implementar el algoritmo desde cero, se mide por reconocer cuándo ese no es el problema que hay que resolver. La habilidad diferenciadora es saber leer la documentación de una herramienta especializada, modelar correctamente las restricciones del negocio como su entrada, y construir el resto del sistema alrededor de ella con la misma seriedad que se le daría a un componente propio.