旅行推销员2-opt代码留下交叉边缘

时间:2015-02-21 05:36:26

标签: c# optimization traveling-salesman

我尝试实施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;
        }

2 个答案:

答案 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是交换边的端点,则相同。