¿Puede alguien darme una muestra del código del algoritmo 2-opt para el problema del vendedor ambulante? Por ahora estoy usando el vecino más cercano para encontrar el camino, pero este método está lejos de ser perfecto, y después de algunas investigaciones encontré el algoritmo 2-opt que corregiría ese camino hasta el nivel aceptable. Encontré algunas aplicaciones de muestra pero sin código fuente.problema del vendedor ambulante, algoritmo 2-opt implementación C#
Respuesta
Así que me aburrí y lo escribí. Es parece como funciona, pero no lo he probado muy a fondo. Asume la desigualdad del triángulo, existen todos los bordes, ese tipo de cosas. Funciona en gran medida como la respuesta que describí. Imprime cada iteración; el último es el 2-optimizado.
Estoy seguro de que se puede mejorar en un trillón de maneras.
using System;
using System.Collections.Generic;
using System.Linq;
namespace TSP
{
internal static class Program
{
private static void Main(string[] args)
{
//create an initial tour out of nearest neighbors
var stops = Enumerable.Range(1, 10)
.Select(i => new Stop(new City(i)))
.NearestNeighbors()
.ToList();
//create next pointers between them
stops.Connect(true);
//wrap in a tour object
Tour startingTour = new Tour(stops);
//the actual algorithm
while (true)
{
Console.WriteLine(startingTour);
var newTour = startingTour.GenerateMutations()
.MinBy(tour => tour.Cost());
if (newTour.Cost() < startingTour.Cost()) startingTour = newTour;
else break;
}
Console.ReadLine();
}
private class City
{
private static Random rand = new Random();
public City(int cityName)
{
X = rand.NextDouble() * 100;
Y = rand.NextDouble() * 100;
CityName = cityName;
}
public double X { get; private set; }
public double Y { get; private set; }
public int CityName { get; private set; }
}
private class Stop
{
public Stop(City city)
{
City = city;
}
public Stop Next { get; set; }
public City City { get; set; }
public Stop Clone()
{
return new Stop(City);
}
public static double Distance(Stop first, Stop other)
{
return Math.Sqrt(
Math.Pow(first.City.X - other.City.X, 2) +
Math.Pow(first.City.Y - other.City.Y, 2));
}
//list of nodes, including this one, that we can get to
public IEnumerable<Stop> CanGetTo()
{
var current = this;
while (true)
{
yield return current;
current = current.Next;
if (current == this) break;
}
}
public override bool Equals(object obj)
{
return City == ((Stop)obj).City;
}
public override int GetHashCode()
{
return City.GetHashCode();
}
public override string ToString()
{
return City.CityName.ToString();
}
}
private class Tour
{
public Tour(IEnumerable<Stop> stops)
{
Anchor = stops.First();
}
//the set of tours we can make with 2-opt out of this one
public IEnumerable<Tour> GenerateMutations()
{
for (Stop stop = Anchor; stop.Next != Anchor; stop = stop.Next)
{
//skip the next one, since you can't swap with that
Stop current = stop.Next.Next;
while (current != Anchor)
{
yield return CloneWithSwap(stop.City, current.City);
current = current.Next;
}
}
}
public Stop Anchor { get; set; }
public Tour CloneWithSwap(City firstCity, City secondCity)
{
Stop firstFrom = null, secondFrom = null;
var stops = UnconnectedClones();
stops.Connect(true);
foreach (Stop stop in stops)
{
if (stop.City == firstCity) firstFrom = stop;
if (stop.City == secondCity) secondFrom = stop;
}
//the swap part
var firstTo = firstFrom.Next;
var secondTo = secondFrom.Next;
//reverse all of the links between the swaps
firstTo.CanGetTo()
.TakeWhile(stop => stop != secondTo)
.Reverse()
.Connect(false);
firstTo.Next = secondTo;
firstFrom.Next = secondFrom;
var tour = new Tour(stops);
return tour;
}
public IList<Stop> UnconnectedClones()
{
return Cycle().Select(stop => stop.Clone()).ToList();
}
public double Cost()
{
return Cycle().Aggregate(
0.0,
(sum, stop) =>
sum + Stop.Distance(stop, stop.Next));
}
private IEnumerable<Stop> Cycle()
{
return Anchor.CanGetTo();
}
public override string ToString()
{
string path = String.Join(
"->",
Cycle().Select(stop => stop.ToString()).ToArray());
return String.Format("Cost: {0}, Path:{1}", Cost(), path);
}
}
//take an ordered list of nodes and set their next properties
private static void Connect(this IEnumerable<Stop> stops, bool loop)
{
Stop prev = null, first = null;
foreach (var stop in stops)
{
if (first == null) first = stop;
if (prev != null) prev.Next = stop;
prev = stop;
}
if (loop)
{
prev.Next = first;
}
}
//T with the smallest func(T)
private static T MinBy<T, TComparable>(
this IEnumerable<T> xs,
Func<T, TComparable> func)
where TComparable : IComparable<TComparable>
{
return xs.DefaultIfEmpty().Aggregate(
(maxSoFar, elem) =>
func(elem).CompareTo(func(maxSoFar)) > 0 ? maxSoFar : elem);
}
//return an ordered nearest neighbor set
private static IEnumerable<Stop> NearestNeighbors(this IEnumerable<Stop> stops)
{
var stopsLeft = stops.ToList();
for (var stop = stopsLeft.First();
stop != null;
stop = stopsLeft.MinBy(s => Stop.Distance(stop, s)))
{
stopsLeft.Remove(stop);
yield return stop;
}
}
}
}
aunque parece que no puedo lograr que se formatee correctamente. –
+1 por realmente dar una implementación de trabajo * casi * –
¡realmente funciona! – garik
Bueno, su solución para TSP siempre estará lejos de ser perfecta. Sin código, pero he aquí cómo hacer para 2-Opt. No es tan malo:
- Necesita una clase llamada Stop que tenga una propiedad Next, Prev y City, y probablemente una propiedad Stops que solo devuelva la matriz que contiene Next y Prev.
- Cuando los vincules, lo llamaremos Tour. Tour tiene una propiedad Stop (cualquiera de las paradas lo hará), y una propiedad AllStops, cuyo comprador solo camina por las paradas y las devuelve
- Necesita un método que realice un recorrido y le devuelva el costo. Vamos a llamar a eso Tour.Cost().
- Necesita Tour.Clone(), que simplemente recorre las paradas y las clona individualmente
- Necesita un método que genere el conjunto de recorridos con dos bordes conmutados. Llame a este Tour.PossibleMutations()
- de inicio con su solución NN
- PossibleMutations de llamada() sobre ella
- Costo de llamada() en todos ellos y tomar el uno con el resultado más bajo
- Repita hasta que el costo no baja
Si vas a usar Bruteforce, ¿por qué no encuentras el óptimo? –
@Moron: no estoy seguro de entender la relación entre los árboles de expansión mínima y 2-opt. ¿Estás diciendo que usas el preorden MST y luego aplicas 2-opt, o algo más? –
Mi culpa. Estaba pensando que 2-opt significa el doble de óptimo, en cuyo caso MST funciona. Borré mi respuesta –
Si el problema es la distancia euclidiana y desea que el coste de la solución producida por el algoritmo está dentro de 3/2 de la óptima, entonces quieren que el algoritmo de christofides. ACO y GA no tienen un costo garantizado.
- 1. bordes de cruce en el problema del vendedor ambulante
- 2. Vendedor ambulante simplificado en Prolog
- 3. Ejemplo vendedor ambulante con óptimo global conocido
- 4. ¿Has usado un algoritmo de vendedor ambulante para resolver un problema?
- 5. ¿Solución al problema del vendedor ambulante usando el algoritmo del vecino más cercano en una consulta LINQ?
- 6. Tratando con gráficos masivos - Vendedor ambulante
- 7. Cómo resolver el problema del vendedor ambulante en ruby (más de 50 ubicaciones)
- 8. Uso de A * para resolver al Vendedor ambulante
- 9. ¿Qué pasa con mi solución de red neuronal de Hopfield para el problema del vendedor ambulante?
- 10. Vendedor ambulante Representación de restricción de problemas
- 11. Implementación de C# del algoritmo Bron-Kerbosch
- 12. Implementación del algoritmo C5?
- 13. Implementación del algoritmo Bentley-Ottmann
- 14. Implementación del algoritmo de Dijkstra
- 15. Encontrando la implementación del algoritmo del árbol de intervalos C++
- 16. Implementación máxima del algoritmo de rectángulo
- 17. Implementación del algoritmo de ordenación más segura
- 18. Implementación C# del 'Algoritmo de polilínea codificada' de Google
- 19. Implementación del algoritmo Bentley-Ottmann existente
- 20. Manejar varios controladores JDBC del MISMO VENDEDOR
- 21. ¿Cuál es la diferencia entre un vendedor ambulante y un viajero chino?
- 22. Problema de implementación del generador de parásitos LALR
- 23. Una pregunta detallada al aplicar algoritmo genético al vendedor viajero
- 24. Implementación del algoritmo de Luhn en Ruby
- 25. Implementación del algoritmo DPLL en Prolog
- 26. Implementación de Python del algoritmo OPTICS (Clustering)
- 27. Implementación del algoritmo de triangulación Chazelle
- 28. Implementación de Python del algoritmo de Viterbi
- 29. Implementación MySQL del algoritmo Ray-Casting?
- 30. problema del estadio: Proporcione un algoritmo para resolver el problema
Existe una solución 3/2 OPT para TSP, por lo que si observa el rendimiento, entonces será mejor (no, no tengo el código pero puedo decir el algo, o puede leerlo en el capítulo 2 de vijay vazirani) – anon