旅行推销员本地搜索启发式

时间:2015-04-26 14:27:18

标签: java debugging traveling-salesman hamiltonian-cycle

我正在尝试创建一个本地搜索启发式来解决TSP,这个过程似乎失败了。我已经生成了一个随机哈密顿循环并将其存储在outgoing []中,其中outgoing [i]表示起始于i的一个边指向的顶点。距离[a] [b]表示从顶点a到顶点b的距离。然而,每当我运行该代码时,该算法不是优化我在传出中传递的哈密顿循环,而是简单地创建新的循环0->数量-2-> 1->数量-1。它应该简单地重复切换输出顶点,如果它可以改善顶点到其输出顶点的距离。我可能忽略了一些小事,但我根本无法弄清楚我做错了什么。顺便说一句,我将运行这么多次,这就是布尔改变的用途。

for(int i = 0; i < numcities; i++)
{
   for(int j = i+1; j < numcities; j++)
   {
      if(distances[i][outgoing[i]] + distances[j][outgoing[j]] > distances[i][outgoing[j]] + distances[j][outgoing[i]] && i != outgoing[j] && j != outgoing[i])
      {
        changed = true;
        int temp = outgoing[j];
        outgoing[j] = outgoing[i];
        outgoing[i] = temp;
      }
    }
}

1 个答案:

答案 0 :(得分:1)

问题在于,当你交换outgoing[i]outgoing[j]时,你会创建两个小子 - 两个较小的周期。

例如,假设numcities=6并且您的首发之旅为0 1 2 3 4 5.假设您的if声明适用于i=1j=3。您的代码集outgoing[1] = 4outgoing[3] = 2。所以代码认为自outgoing[1] = 4以来巡回演出现在是0 1 4 5。这不是你正在进行的巡回演出,但我认为这是基本的想法。

要解决此问题,您需要将游览分为3个部分 - (A)部分直至并包括城市i,(B)i和{{1之间的部分(包括j)和(C)j之后的部分。当您交换边缘时,您需要重新配置巡视,因此(A)与之前相同,然后部分(B)反转,然后部分(C)完好无损。

所以在我的例子中,部分(A)是0 1,部分(B)是2 3,部分(C)是4 5.打破边缘1-2和3-4,然后重新连接,你得到游览0 1 3 2 4 5.

您在此处实施的内容称为 2-opt 。您可以在很多地方找到更多相关信息。