【问题标题】:Java: Traveling Salesman - Found polynomial algorithmJava:旅行推销员 - 找到多项式算法
【发布时间】:2013-10-19 05:04:21
【问题描述】:

编辑:找到此算法的improvement。欢迎大家观看。

这个问题是我的old 问题的改进。现在我想向您展示Java code sample,并更详细地解释我的算法。

我认为我找到了一个多项式算法来获得旅行商问题的精确解。我的实现是从 5 个步骤构建的:

  • 1) 快速设置
  • 2) 寻找解决方案
  • 3) 停止条件 1
  • 4) 停止条件 2
  • 5) 停止条件 3

我想从第 2 步和第 3 步开始,如果我没有弄错,我会告诉你剩下的。

所以我现在要向您展示的,不是多项式算法,而是对Held–Karp algorithm 的改进,可以在 O(n^2 2^n) 时间内解决问题

假设我们想用 brout 算法解决 6 个城市的路线。有(6-1)! = 120 选项,我们需要对它们全部进行测试并返回建立的最短路径。所以它看起来像这样(城市名称是:A、B、C、D、E、F):

  • 选项 1:A -> B -> C -> D -> E -> F -> A
  • 选项 2:A -> B -> C -> D -> F -> E -> A
  • 选项 3:A -> C -> B -> D -> E -> F -> A
  • 选项 4:A -> C -> B -> D -> F -> E -> 一个
  • .
  • .
  • 选项 120

现在我是说,在计算了选项 1 和 2 之后,你可以跳过选项 3 和 4。你是怎么做到的?很简单:在计算选项 1 时,您需要计算从 D 市开始,在 A 市结束,经过 E、F 城市的最短路线,它实际上是在计算选项 1 和 2。我们要做的是构建一个包含 4 个城市的地图,我们在其中强制执行第一个和最后一个城市,在此示例中,在计算选项 1 时,您创建一个 D、E、F、A 地图,其中包含最短路径的数据D 到 A 到 E、F。因此,现在当您开始计算选项 3 和 4 时,您可以在到达 D 市时停下来,因为您已经知道从 D 市开始、在 A 市结束并经过 E、F 市的最短路线。

这是我在算法中使用的原理。我运行了一个蛮力算法并映射了所有子结果,那些结果不是子路由,不要在那里混淆。它们只是为了找到最短路径而需要完成的计算的一部分。所以每次我意识到我在做同样的计算时,我都会使用地图中的解决方案。

这是我的算法在 19 个城市运行的输出。这只是一个样本,但它的意义远不止于此。事实上,它代表了 19 个城市的所有结果。无论 19 个城市的输入是什么,算法总是会创建相同数量的地图,执行相同数量的操作,并且会在相同的时间内解决。

Source(19)  [10.0,65.0, 34.0,52.0, 37.0,98.0, 39.0,44.0, 43.0,37.0, 45.0,89.0, 66.0,79.0, 69.0,74.0, 7.0,76.0, 70.0,15.0, 77.0,27.0, 78.0,11.0, 78.0,13.0, 80.0,5.0, 81.0,38.0, 82.0,64.0, 87.0,7.0, 90.0,61.0, 93.0,31.0]
Finish MapEngine test after 321550 mills
Created: 20801457
Map(3)  Write    2448       Read     34272
Map(4)  Write    12240      Read     159120
Map(5)  Write    42840      Read     514080
Map(6)  Write    111384     Read     1225224
Map(7)  Write    222768     Read     2227680
Map(8)  Write    350064     Read     3150576
Map(9)  Write    437580     Read     3500640
Map(10) Write    437580     Read     3084270
Map(11) Write    352185     Read     2344256
Map(12) Write    245131     Read     1382525
Map(13) Write    135638     Read     570522
Map(14) Write    54320      Read     156758
Map(15) Write    15077      Read     27058
Map(16) Write    2809       Read     2087
Map(17) Write    306        Read     0
Map(18) Write    18         Read     0
Map(19) Write    1          Read     0

0) 295.5947584525372>   [10.0,65.0, 34.0,52.0, 39.0,44.0, 43.0,37.0, 70.0,15.0, 78.0,13.0, 78.0,11.0, 80.0,5.0, 87.0,7.0, 77.0,27.0, 93.0,31.0, 81.0,38.0, 90.0,61.0, 82.0,64.0, 69.0,74.0, 66.0,79.0, 45.0,89.0, 37.0,98.0, 7.0,76.0, 10.0,65.0]

Source(19) 是输入城市。我的电脑321550 mills 计算了(大约 5 分钟)。 Created: 20801457 表示创建的搜索实例的数量(我使用地图或创建地图的所有时间。您需要查看代码才能更好地理解这个数字)。 Map(3) 谈到了已创建的 3 个城市的地图数量。创建了2448张3城地图,使用了34272次。

我的算法将在 N 个城市路线中生成具有 K 个城市大小的地图数量为:我可以选择地图的第一个城市的次数:N 乘以次数我可以从其余城市中选择不同的城市:(n-1)! /((n - k - 1)!*(k-1)!)。来n! / ((n - k - 1)! * (k-1)!)。假设创建一个大小为 3 的地图是一个原子动作,那么我的算法效率将是所有这些地图的总和。

所以我的算法有下一个效率。

N * (N - 1) * (N - 2) / 2! + N * (N - 1) * (N - 2) * (N - 3) / 3! + N * (N - 1) * (N - 2) * (N - 3) (N -4) / 4! + ... N! /(N - 1)! = N * (N - 1) * (N - 2) / 2! + N * (N - 1) * (N - 2) * (N - 3) / 3! + N * (N - 1) * (N - 2) * (N - 3) (N -4) / 4! + ... N

那么这是一种什么样的效率呢?

它看起来像 O(N^C*2^N) 的指数函数,其中 C 比 1 小一点。我通过求解效率算法找到了这一点,N 从 7 到 100,并将其与之前的结果(N = 9 和 N = 8 的结果,N = 24 和 N = 23 的结果)进行比较,我发现对于N的大数比较结果是2。然后我用传统的动态规划算法效率做了同样的事情。这是我得到的清单:

第1列是N,第2列是我的算法效率比较,第3列是动态规划算法比较,第4列是我的算法效率乘N比较。

7   2.55769     2.72222     2.98397 
8   2.40601     2.61224     2.74973 
9   2.31562     2.53125     2.60507 
10  2.2582      2.46913     2.50912 
11  2.21972     2.42        2.44169 
12  2.19258     2.38016     2.39191 
13  2.17251     2.34722     2.35356 
14  2.15701     2.31952     2.32293 
15  2.14456     2.29591     2.29774 
16  2.13424     2.27555     2.27652 
17  2.12548     2.25781     2.25832 
18  2.1179      2.24221     2.24248 
19  2.11124     2.22839     2.22853 
20  2.10533     2.21606     2.21614 
21  2.10003     2.205       2.20503 
22  2.09525     2.19501     2.19503 
23  2.09091     2.18595     2.18596 
24  2.08696     2.17769     2.17769 
25  2.08333     2.17013     2.17014 
26  2.08        2.1632      2.1632 
27  2.07692     2.1568      2.1568 
28  2.07407     2.15089     2.15089 
29  2.07142     2.1454      2.1454 
30  2.06896     2.1403      2.1403 
31  2.06666     2.13555     2.13555 
32  2.06451     2.13111     2.13111 
33  2.0625      2.12695     2.12695 
34  2.0606      2.12304     2.12304 
35  2.05882     2.11937     2.11937 
36  2.05714     2.11591     2.11591 
37  2.05555     2.11265     2.11265 
38  2.05405     2.10956     2.10956 
39  2.05263     2.10664     2.10664 
40  2.05128     2.10387     2.10387 
41  2.05        2.10125     2.10125 
42  2.04878     2.09875     2.09875 
43  2.04761     2.09637     2.09637 
44  2.04651     2.0941      2.0941 
45  2.04545     2.09194     2.09194 
46  2.04444     2.08987     2.08987 
47  2.04347     2.0879      2.0879 
48  2.04255     2.08601     2.08601 
49  2.04166     2.0842      2.0842 
50  2.04081     2.08246     2.08246 
51  2.04        2.0808      2.0808 
52  2.03921     2.0792      2.0792 
53  2.03846     2.07766     2.07766 
54  2.03773     2.07618     2.07618 
55  2.03703     2.07475     2.07475 
56  2.03636     2.07338     2.07338 
57  2.03571     2.07206     2.07206 
58  2.03508     2.07079     2.07079 
59  2.03448     2.06956     2.06956 
60  2.03389     2.06837     2.06837 
61  2.03333     2.06722     2.06722 
62  2.03278     2.06611     2.06611 
63  2.03225     2.06503     2.06503 
64  2.03174     2.06399     2.06399 
65  2.03125     2.06298     2.06298 
66  2.03076     2.06201     2.06201 
67  2.0303      2.06106     2.06106 
68  2.02985     2.06014     2.06014 
69  2.02941     2.05925     2.05925 
70  2.02898     2.05839     2.05839 
71  2.02857     2.05755     2.05755 
72  2.02816     2.05673     2.05673 
73  2.02777     2.05594     2.05594 
74  2.02739     2.05516     2.05516 
75  2.02702     2.05441     2.05441 
76  2.02666     2.05368     2.05368 
77  2.02631     2.05297     2.05297 
78  2.02597     2.05228     2.05228 
79  2.02564     2.05161     2.05161 
80  2.02531     2.05095     2.05095 
81  2.025       2.05031     2.05031 
82  2.02469     2.04968     2.04968 
83  2.02439     2.04907     2.04907 
84  2.02409     2.04848     2.04848 
85  2.0238      2.0479      2.0479 
86  2.02352     2.04733     2.04733 
87  2.02325     2.04678     2.04678 
88  2.02298     2.04624     2.04624 
89  2.02272     2.04571     2.04571 
90  2.02247     2.04519     2.04519 
91  2.02222     2.04469     2.04469 
92  2.02197     2.04419     2.04419 
93  2.02173     2.04371     2.04371 
94  2.0215      2.04324     2.04324 
95  2.02127     2.04277     2.04277 
96  2.02105     2.04232     2.04232 
97  2.02083     2.04188     2.04188 
98  2.02061     2.04144     2.04144 
99  2.0204      2.04102     2.04102 
100 2.0202      2.0406      2.0406 

看看第 3 列和第 4 列几乎相同。我就是这样找到它的。

请验证我的工作,看看代码,告诉我你是否同意我的观点。如果不是,请通过精确样本告诉我我的算法或数学在哪里不起作用。如果你同意我的观点,那么请帮助我更改 wiki 页面,证明我的这部分算法比 Held–Karp 算法更好。

【问题讨论】:

  • 如果您认为您找到了多项式旅行商解决方案,那么您应该发表一篇科学论文,而不是 Stackoverflow 问题。
  • 所以 NP = P 并且不再存在难题,幸运的世界!
  • 您还没有意识到您的方法不起作用?知道子链的最佳路线的基本假设可以在添加更多城市后简单地将子链替换为更大的组合中的最佳是错误的。您已经被告知,在您的其他问题之一中,您的方法实际上没有找到样本问题的最佳解决方案:cs.stackexchange.com/questions/14902 在做出特别声明之前让您的方法至少正常工作怎么样?浪费大家的时间。拒绝看到问题并不能让它消失!
  • @Durandal 这个问题与你提到的问题无关(我确实有错误,我已经修复了)。这是两个不同的东西,这就是为什么它们被发布在不同的问题中。另外,如果您认为我的假设是错误的,请证明它。我什至附上了源代码,告诉我一个我错的案例。
  • @Phpdna 附有代码,只需将设置中的 ShowGuid 布尔值设置为 true,您将获得大量样本。另请阅读我的上一篇文章更新,了解为什么一个例子就足够了。

标签: java graph traveling-salesman np-complete np-hard


【解决方案1】:

简而言之:就问题的复杂性而言,您的方法一无所获。

让我们看看您的方法的复杂性。您实际上正在做的是计算所有子路径的传递闭包,同时消除在同一城市开始和结束的每两个子路径中较长的部分,以减少下一次迭代的剩余组合数量。假设您将每对城市之间的距离存储在哈希图中,因此查找时间在 O(1) 内。

鉴于您有 n 个城市要包含在您的路线中,因此有 n x (n-1) 对。

要计算所有长度为 3 的子路径的距离,您选择了一个城市并将其与本身不包含所选城市的每一对组合。有 (n-1) x (n-2) 个这样的对。由于您有 *n) 个城市可供选择作为第一个位置,因此您有 3 x 2 x 1 个长度为 3 的路径要计算。对于 n = 3,这意味着您有 O(n!)。

要计算所有长度为 4 的子路径的距离,请重复该过程。这次您需要 4 x 3 x 2 x 1 计算。对于 n = 4,这意味着您有 O(n!)。这是您的消除开始发挥作用的地方。从同一城市开始和结束的每两条路径中,您只需要记住较短的一条。这意味着只剩下 (4 x 3 x 2 x 1)/2 个长度为 4 的路径。

要计算所有长度为 5 的子路径的距离,您可以从上一步中的消除中获益。您只需要计算 5 x (4 x 3 x 2 x 1)/2。对于 n = 5,这意味着您有 O(1/2 x n!) = O(n!)。这一次,您可以消除 6 条路径中的 5 条,这些路径起点和终点都在同一个城市(其中一些您甚至没有计算,因为上一步中已消除),剩下 (5 x 4 x 3 x 2 x 1)/6 路径长度为 5。

因此,对于 n = 6,您有 O(1/6 x n!),仍然是 O(n!)。对于每进一步的步骤,该因子将变得更小。这意味着您的算法比不保存任何中间结果的天真蛮力方法更快。但是您的复杂性仍然 O(n!)。

【讨论】:

  • 如果这是真的,我将能够计算出 19 个城市的路径,即 18 个! = 6.40237370e+15。所以你有一个错误,我会向你解释它是什么。你认为如果我计算城市 A,B,C,D,我还需要计算城市 [A,B,D,C], [A,C,B,D], [A,C,D ,B], [A,D,C,B], [A,D,B,C],但事实并非如此。我是您可以从 N - 2 中选择的储蓄 k - 1(在本例中为 k = 4)个城市(顺序不重要且不允许重复)。公式为:N! / ((N - R)!(R!))
  • 您在帖子中没有说明任何内容可以使您免于计算所有这些排列。您声明不必计算选项 2,因为您已经与选项 1 一起计算对我来说毫无意义,因为您仍在进行计算,只是在其他地方进行。
  • 那我不知道如何说服你,而不是向你展示事实。该算法在不到 6 分钟的时间内解决了 19 个城市的地图。看看代码,再看看我的解释,试着解释这怎么可能。
  • 在关于复杂性的讨论中,计算时间不是论据。您总是可以在问题上投入更多的硬件。这不会降低复杂性。如果你甚至不能解释为什么你认为你可以跳过一些计算,你怎么能确定你的结果是正确的?
  • 你没看懂大O。O(n!)不代表有n!要执行的动作。顺便说一句,18!根据我的 windows 计算器是6.402.373.705.728.000。
【解决方案2】:

您的工作似乎落在四个关键点上:

  1. 您似乎不明白多项式时间的含义
  2. 您的算法似乎无法解决一般的旅行商问题
  3. 即使您的算法解决的问题是旅行商问题,它也是基于错误的假设,导致它给出错误的答案
  4. 即使您的算法正确解决了正确的问题,它似乎也不会在多项式时间内运行

对于第 1 点,多项式时间算法不是可以在五分钟内在家用计算机上运行的算法。术语“poly time”、“constant time”、“log time”等都是指算法缩放的方式。提供一次算法运行的结果并没有告诉我们任何关于这一点的信息。为了提供算法渐近运行时间的经验数据,您需要对大量随机问题实例进行平均。例如,this graph 提供的证据表明,在二维中,用于跨 n 个随机点的范围报告的简单方法是使用简单方法的O(n) 和使用二维树的O(n^0.5)。我解决了 10,000 个随机生成的问题,点的数量范围从 2 到 2^(20),并在一些对数尺度上绘制了完成时间 - 这些线的梯度为算法的渐近运行时间提供了证据。

一次试验的结果几乎毫无意义。如果你不能严格证明一个算法是多项式的,那么一组经过充分分析的经验结果将为你的主张提供证据并引起人们的兴趣。我必须非常强调“大”这个词。

对于第二点,您的算法解决了欧几里得旅行商问题,而不是旅行商问题。这些是不同的问题。尽管这种区别是技术性的,而且 ETSP 仍然是 NP 难的,但您没有在关于该主题的 7 个问题中的任何一个中解决它甚至提到它的事实表明您在声称您的解决方案之前没有充分研究该领域是有效。

对于第三点,根据我从您的问题中可以理解的情况,您的解决方案是基于这样的假设,即通过顶点D E F A 的最短哈密顿路径与通过顶点E F A 的最短哈密顿路径有某种关联。这是错误的。假设E->F->A 是通过这些顶点的最短路径。如果D 接近E 并选择DEF 与按该顺序出现的顶点共线,则最短路径为D->E->F->A。如果选择D 位于E 和F 之间的中间,则最短路径为E->D->F->A。与之前类似的选择可以为我们提供顶点排列,使得E->F->D->A 和E->F->A->D 是最短路径,并且这样的构造可以推广到任意数量的顶点。知道通过某个顶点子集的最短哈密顿路径不会告诉您涉及另一个顶点时的情况。

确实,从您的一个测试用例中,您的算法has been shown 会产生不正确的结果。你没有解释在这种情况下发生了什么,也没有说明你是如何解决这个问题的,或者你是否已经解决了这个问题。

最后,你给出的总和大于binomial coefficients 与 n 的总和。本站似乎不支持LaTeX,所以我们将使用(nCk) 表示二项式系数n 选择k。您的总和可以重写为(k)(n-k)(nCk) 的总和k=1 to n。对于k=1 to n,这个和显然大于(nCk) 的和,所以这个和必须大于2^n,所以根据你的分析,你的算法肯定不是多项式的。任何涉及一堆阶乘的总和都不太可能是多项式有界的。如果您需要任何类型的非平凡组合来表达您的算法的运行时间,它可能不会在多项式时间内执行。

【讨论】:

  • 感谢您的回答 ymbirtt,但您似乎没有阅读我的底线或顶部的底线。这只是我算法的第二部分,我试图证明我找到了比 Held–Karp 算法更好的解决方案,时间为 O(2^N N^2)。我在这里只展示一个示例,因为我的算法将同时解决所有 19 个城市,计算相同的动作。另外,我认为您不了解我的示例。我没有显示 4 个选项,而是所有可能的 120 个选项。我是说我在解释为​​什么我可以避免测试其中的 30 个。
  • 我刚刚对问题进行了重大编辑。现在解释为什么19个城市的一个例子就足够了;如何保存计算;以及为什么我说它是多项式时间,而它不是。我还解释了我在以前的帖子中的错误。另外我可以保证这里没有错误。
  • 首先,我想建议不要对您的问题进行多次重大更改。其次,我确实阅读了您问题的第一部分和最后一部分-但是,如果您的算法的一部分基于错误的假设并且至少需要 2^n 时间,而没有表明您的预处理步骤是做什么的围绕这一点,考虑其余部分没有什么意义。
  • 程序的经验运行时间实际上是一个随机数,因此在提供实际数据时,最好的做法是取多个值并对它们进行平均。我记得之前的帖子 - cs.stackexchange.com/q/14998/10236 - 但是你无法测试超过 19 个城市的任何东西,所以我很好奇你是如何收集这些数据的。您也没有指定这些数字实际上是什么。虽然衡量你的时间的单位是无关紧要的,但你的“效率”似乎会随着问题的大小而降低这一事实至少很奇怪。
  • 最后,在过去的几天里,我反复阅读了您的缓存方案,但我完全看不出它如何为您节省任何工作。如果您考虑每条可能的路径,那么您考虑每条路径所花费的时间是无关紧要的。你还考虑过(n-1)!路径,这使您的算法并不比蛮力解决方案更好。我注意到您现在已经明确表示“我是说它是多项式时间,而它不是”。如果您的算法不是多项式时间,我认为没有理由声称它是。
【解决方案3】:

我将尝试将其分解为基本要素。但首先让我赞扬你解决了一个“已知”非常困难的问题。不冒险就无法取得进展。

您正在根据 S(a, b, I) 的递归表达式接近 TSP,从城市 a 到城市 b 的最短路径的长度,a \ne b,通过无序集合 I 中的每个城市恰好一次。

有了 S,TSP 很容易解决。对于城市集 C,找到

min( D(b, a) + S(a, b, C\a\b) ) over all pairs a, b drawn from C where a \ne b

这里 D(x, y) = D(y, x) 是城市 x 到 y 的距离,C\a\b 是去掉 a 和 b 的 C。

你为 S 提出的递归表达式是

S(a, b, I) = min( D(a, p) + S(p, q, I\p\q) + D(q, b) ) 
               over all pairs p, q drawn from I where p \ne q ,  

基本情况是我有零个或一个元素。这些都很明显。

您建议缓存 S(a, b, I) 的值,以便不再重复此类计算。 (顺便说一下,这被称为记忆。)

那么这个计算的成本是多少,或者相当于缓存的大小?我们可以为它写一个递归式,其中参数 n = |I|是中间集中的城市数量:

C(n) = M(n, 2) C(n - 2) = ( n(n-1)/2 )  C(n - 2)
C(0) = C(1) = 1

这里 M(n, m) 是 n 次取 m 的东西的组合,n! / (m!(n-m)!)

我们可以解决这个问题。偶数n:

C(n) = n! /  2^(n/2)

我会让你解决奇怪的情况。

对于 m 个城市之间的旅行,我们需要对所有城市对和相应的中间集重复此操作:

(m(m-1)/2) C(m-2) = m! / 2^(m/2-2)

所以你的方法确实避免了相对于生成所有可能的旅行的朴素算法的指数工作量,但阶乘仍然占主导地位:这个函数是超指数的。

注意您的其他“停止标准:”以上是仅计算一次 S(a,b,I) 的所有可能值的成本。要获得多时间算法,您必须想出一个完全跳过三元组的超指数数 (a,b,I) 的方案。你不太可能做到这一点,但不要让这削弱你的热情。

【讨论】:

  • Tnx,基因。实际上这只是一个开始,我得到了很大的改进,并且非常接近多项式解决方案。您可以在stack exchange 找到我最反感的帖子。我得到了理论,现在正在尝试实施它。到目前为止,我可以在 6 秒内完成 21 个长度的城市,在我的笔记本电脑上,它还不是 poly,但肯定是那些记录。
猜你喜欢
  • 2013-06-09
  • 2017-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-28
  • 2021-01-19
  • 2011-09-08
  • 1970-01-01
相关资源
最近更新 更多