37. Problema del viajante (TSP)

El problema del viajante busca el recorrido cerrado de menor costo que visita cada ciudad exactamente una vez. Es fácil describirlo, pero resolverlo de forma óptima puede requerir explorar una cantidad enorme de posibilidades.

37.1 Introducción

Un viajante debe salir de una ciudad, visitar todas las demás una sola vez y regresar al inicio. Cada traslado tiene un costo, que puede representar distancia, tiempo, dinero o consumo de energía.

El objetivo es minimizar la suma total. TSP es uno de los problemas más estudiados de optimización combinatoria y sirve como modelo para numerosas tareas de planificación.

37.2 Definición formal

Dado un grafo ponderado G = (V,E), se busca un ciclo que visite cada vértice exactamente una vez y regrese al vértice inicial, minimizando el costo.

minimizar Σ w(vi,vi+1), incluyendo el regreso vn → v1

Si alguna conexión no existe, puede considerarse de costo infinito o trabajarse directamente sobre el grafo incompleto.

37.3 Relación con los ciclos hamiltonianos

Una ruta válida de TSP es un ciclo hamiltoniano: visita todos los vértices exactamente una vez. TSP agrega el objetivo de encontrar el de menor peso.

Determinar si existe un ciclo hamiltoniano puede reducirse a una instancia de TSP, lo que ayuda a explicar la dificultad computacional del problema.

37.4 TSP simétrico y asimétrico

VariantePropiedadEjemplo
Simétricow(u,v) = w(v,u)Distancias euclidianas
Asimétricow(u,v) puede diferir de w(v,u)Calles de un sentido o tarifas

En el caso simétrico, recorrer un ciclo en sentido inverso tiene el mismo costo.

37.5 TSP métrico

Una instancia es métrica cuando los costos son simétricos y cumplen la desigualdad triangular.

w(u,v) ≤ w(u,x) + w(x,v)

Ir directamente nunca es peor que desviarse por otro vértice. Esta propiedad permite algoritmos de aproximación con garantías que no existen para el TSP general.

37.6 Laboratorio de rutas y 2-opt

Comienza con el orden alfabético o construye una ruta por vecino más cercano. Después aplica 2-opt para reemplazar dos aristas cuando la inversión de un segmento reduce la distancia.

Ruta actual

Último intercambio

Ninguno

Acción actual

Ruta alfabética preparada.
Puedes mejorar la ruta.
Distancia inicial0
Distancia actual0
Mejora acumulada0
Intercambios 2-opt0

2-opt elimina cruces y otras desviaciones evidentes, pero detenerse sin mejoras solo certifica un óptimo local.

37.7 Crecimiento factorial

Fijando una ciudad inicial, existen (n − 1)! órdenes posibles. En TSP simétrico, una ruta y su inversa son equivalentes, por lo que quedan (n − 1)! / 2 ciclos distintos.

10 ciudades ⇒ 9! / 2 = 181 440 rutas
20 ciudades ⇒ 19! / 2 ≈ 6,08 × 10¹⁶ rutas

37.8 Fuerza bruta

Para instancias pequeñas pueden enumerarse todas las permutaciones, calcular el costo de cada ciclo y conservar el menor.

function costoRuta(ruta, distancia) {
  let total = 0;
  for (let i = 0; i < ruta.length; i++) {
    const siguiente = (i + 1) % ruta.length;
    total += distancia[ruta[i]][ruta[siguiente]];
  }
  return total;
}

Fijar la primera ciudad elimina rotaciones equivalentes, pero la complejidad continúa siendo O(n!).

37.9 Ramificación y poda

Branch and bound construye rutas parciales. Si una cota inferior demuestra que una rama no puede mejorar la mejor solución conocida, la descarta.

Una buena solución inicial fortalece la poda. Sin embargo, en el peor caso todavía puede explorarse una cantidad exponencial de estados.

37.10 Programación dinámica de Held-Karp

Held-Karp representa un subproblema mediante un subconjunto S de ciudades visitadas y la última ciudad j.

DP[S][j] = costo mínimo desde el origen, visitando S y terminando en j

La recurrencia prueba como penúltima ciudad cada i de S. Reduce el tiempo factorial a O(n²2ⁿ), a costa de O(n2ⁿ) memoria.

37.11 Implementación de Held-Karp

for (let mascara = 1; mascara < (1 << n); mascara++) {
  for (let ultimo = 0; ultimo < n; ultimo++) {
    if (!(mascara & (1 << ultimo))) continue;
    const anterior = mascara ^ (1 << ultimo);

    for (let previo = 0; previo < n; previo++) {
      if (anterior & (1 << previo)) {
        dp[mascara][ultimo] = Math.min(
          dp[mascara][ultimo],
          dp[anterior][previo] + distancia[previo][ultimo]
        );
      }
    }
  }
}

La inicialización fija una ciudad de origen. Al final se suma el regreso desde la última ciudad al origen.

37.12 Vecino más cercano

La heurística comienza en una ciudad y visita repetidamente la ciudad no visitada más cercana. Es rápida y fácil de implementar.

Tiempo: O(n²) con una matriz de distancias

Puede tomar buenas decisiones iniciales y dejar una conexión final muy costosa. Probar varios puntos de partida suele mejorar el resultado.

37.13 Mejora local 2-opt

2-opt selecciona dos aristas (a,b) y (c,d), las elimina y reconecta (a,c) y (b,d), invirtiendo el segmento intermedio.

Si d(a,c) + d(b,d) < d(a,b) + d(c,d), aceptar el intercambio.

Se repite hasta que ningún intercambio mejora la ruta. En distancias euclidianas elimina todos los cruces, porque un cruce nunca es óptimo.

37.14 Cotas inferiores

Una cota inferior indica un costo que ninguna ruta óptima puede superar hacia abajo. El peso de un árbol de expansión mínima es una cota porque quitar una arista de cualquier ciclo hamiltoniano produce un árbol generador.

peso(MST) ≤ costo(TSP óptimo)

Cotas más fuertes pueden construirse con árboles 1-tree y relajaciones de programación lineal.

37.15 Aproximaciones métricas

En TSP métrico, duplicar las aristas de un MST y acortar vértices repetidos produce una ruta de costo como máximo dos veces el óptimo.

El algoritmo de Christofides combina un MST con un emparejamiento mínimo de los vértices de grado impar y garantiza un factor de aproximación de 3/2.

37.16 Complejidad computacional

La versión de decisión —¿existe una ruta de costo a lo sumo K?— es NP-completa. La versión de optimización es NP-difícil.

No se conoce un algoritmo polinómico que resuelva exactamente todas las instancias. En la práctica se combinan formulaciones enteras, cortes, ramificación y heurísticas.

37.17 Variantes

  • TSP con ventanas de tiempo para cada visita.
  • Múltiples viajantes o vehículos.
  • Premios por visitar ciertos vértices.
  • Rutas abiertas sin regreso al origen.
  • Costos asimétricos.
  • Problema de rutas de vehículos con capacidad.

37.18 Aplicaciones y errores comunes

  • Planificar repartos, inspecciones y recorridos de robots.
  • Ordenar perforaciones en placas electrónicas.
  • Secuenciar tareas con costos de cambio.
  • Olvidar incluir el regreso a la ciudad inicial.
  • Confundir ruta más corta con árbol de expansión mínima.
  • Presentar una heurística como garantía de optimalidad.
  • Usar distancias euclidianas cuando el transporte real es dirigido.

37.19 Qué debes recordar de este tema

  • TSP busca un ciclo hamiltoniano de costo mínimo.
  • Puede ser simétrico, asimétrico o métrico.
  • La enumeración directa crece como O(n!).
  • Held-Karp utiliza O(n²2ⁿ) tiempo.
  • Vecino más cercano construye rápidamente una ruta factible.
  • 2-opt mejora una ruta, pero puede detenerse en un óptimo local.
  • Las cotas permiten evaluar soluciones sin conocer el óptimo.

37.20 Conclusión

TSP muestra la diferencia entre verificar una solución y encontrar la mejor entre un espacio factorial. Las instancias pequeñas admiten métodos exactos; las grandes requieren combinar buenas construcciones, mejoras locales y cotas.

En el próximo tema profundizaremos en los grafos hamiltonianos, la estructura que determina si existe un ciclo capaz de visitar todos los vértices una sola vez.