我尝试实施2-opt优化以发现"足够好" TSP的解决方案,没有边缘交叉。我的印象是2-opt,直到不再进行任何改进,将导致没有过境的巡回演出。但是,由于某种原因,下面的代码不能删除所有交叉边。在1000多个城市的一些运行中,仍有几个交叉点。
代码注释:_solution是一个List。代码不是创建新的游览并计算整个距离,而是计算移除的两个边缘和为速度创建的两个边缘之间的差异。此外,我复制第一个点并添加到列表的末尾,以使计算更简单。因此,i& j范围。
谁能明白为什么这不起作用?
while (!done)
{
bool improved = false;
for (int i = 1; i < _solution.Count - 2; i++)
{
OptimizeSteps++;
for (int j = i + 1; j < _solution.Count - 1; j++)
{
// calculate new tour distance
double newDist = TourLength - CalcPointDistanceL2(_solution[i-1], _solution[i]);
newDist -= CalcPointDistanceL2(_solution[j], _solution[j + 1]);
newDist += CalcPointDistanceL2(_solution[i-1], _solution[j]);
newDist += CalcPointDistanceL2(_solution[i], _solution[j + 1]);
// if shorter make the improved tour
if (newDist < TourLength)
{
// reverse subtour
TSPPoint[] reversedSubTour = new TSPPoint[j-i+1];
_solution.CopyTo( i, reversedSubTour, 0, reversedSubTour.Length );
Array.Reverse( reversedSubTour );
for ( int n = 0; n < reversedSubTour.Length; n++ )
{
_solution[n + i] = reversedSubTour[n];
}
TourLength = newDist;
// debug
double d = GetTotalDistance(_solution);
improved = true;
}
if ( improved ) break;
}
DoNotify(500);
if ( improved ) break;
}
if (!improved) done = true;
}
答案 0 :(得分:0)
在完成2-opt过程后(即,在执行导致较短巡回赛的所有2-opts之后),巡回赛不应该越过自己。
您当前的代码会忽略&#34; j + 1&#34; =起始节点。
您的for j
循环应进一步迭代:
for (int j = i + 1; j < _solution.Count; j++)
如果是j == _solution.Count-1
,那么您应该使用_solution[j + 1]
而不是使用_solution[0]
作为j + 1节点。
答案 1 :(得分:0)
用于改进游览的代码是否正确处理了最后的重复节点?如果重复节点是正在交换的其中一个边的端点,我认为您没有正确调整起始节点 - 如果节点0是交换边的端点,则相同。