gpt4 book ai didi

c# - 旅行商问题,2-opt 算法 c# 实现

转载 作者:可可西里 更新时间:2023-11-01 07:51:25 27 4
gpt4 key购买 nike

谁能给我一个解决旅行商问题的 2-opt 算法的代码示例。现在我使用最近的邻居来寻找路径,但这种方法远非完美,经过一些研究,我发现 2-opt 算法可以将该路径校正到可接受的水平。我找到了一些示例应用程序,但没有源代码。

最佳答案

于是就无聊写了。它看起来有效,但我还没有对其进行非常彻底的测试。它假设三角形不等式,所有边都存在,诸如此类。它的工作原理与我概述的答案很相似。它打印每次迭代;最后一个是 2 优化的。

我相信它可以通过无数种方式得到改进。

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;
}
}
}
}

关于c# - 旅行商问题,2-opt 算法 c# 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2927469/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com