TSP 算法的 BIG O 时间复杂度
Posted
技术标签:
【中文标题】TSP 算法的 BIG O 时间复杂度【英文标题】:BIG O time complexity of TSP algorithms 【发布时间】:2021-04-30 12:29:07 【问题描述】:我在 python 中编写了 2 个最近邻算法,我必须通过 O(n) 和 Θ(n) 来分析运行时复杂度。 所以我尝试了几个样本,但我不明白为什么我的一种算法比另一种更快。
这是我的重复最近邻 (RNN) 算法的代码:
def repeated_nn_tsp(cities):
return shortest_tour(nn_tsp(cities, start) for start in cities)
def shortest_tour(self, tours):
return min(tours, key=self.tour_length)
nn_tsp 的运行时复杂度为 O(n^2),每个起点都会创建一个新的 NN Tour。通过所有 NN 巡回演出,我必须找到最好的巡回演出。 这就是为什么我认为 RNN 的时间复杂度必须是 T(n)=O(n^3) 和 T(n)=Θ(n^3)。
所以这是我的更改最近邻 (ANN) 算法的代码:
def alter_tour(tour):
original_length = tour_length(tour)
for (start, end) in all_segments(len(tour)):
reverse_segment_if_better(tour, start, end)
if tour_length(tour) < original_length:
return alter_tour(tour)
return tour
def all_segments(N):
return [(start, start + length) for length in range(N, 2-1, -1) for start in range(N - length + 1)]
def reverse_segment_if_better(tour, i, j):
A, B, C, D = tour[i-1], tour[i], tour[j-1], tour[j % len(tour)]
if distance(A, B) + distance(C, D) > distance(A, C) + distance(B, D):
tour[i:j] = reversed(tour[i:j])
all_segments 的时间复杂度应该是 T(n) = O(1/2 * n^2 - 0.5n) -> O(n^2) 并创建 n^2 个元素。 在循环内通过 all_segments(通过 n^2 个元素)我调用函数 reverse_segment_if_better。我将使用 python 的反转方法,这会导致 O(n) 的时间复杂度。 这就是为什么我认为循环的时间复杂度必须是 O(n^3)。当有更好的游览时,该函数将调用自身递归。我认为改变后的 NN 的时间复杂度为 O(n^4)。对吗?
但是我们遇到了我的问题:我的评估在 100 个城市上运行代码 100 次,结果表明 ANN 平均比 RNN 快,这与我预期的运行时复杂性相反。 (RNN 需要 4.829 秒,而 ANN 只需要 0.877 秒,1x 100 城市。)
那么我在哪里做错了?
提前致谢!
【问题讨论】:
我可以建议使用 Cprofiler 来获取函数调用的计数和时间。 【参考方案1】:首先我必须说时间复杂性和大 O 符号并不总是正确的,一个算法可能有一个“更好”的运行时间函数,但运行时间仍然比预期慢,或者比另一个最差的函数慢运行时函数,在你的情况下,很难确定什么是最坏的情况来提供算法,我们不能保证你已经做到了!也许这些案例对ANN
算法是“令人愉快的”,而另一个案例被困在某个地方......?这就是为什么仅依靠我们计算的运行时间函数并不总是 100% 正确的原因。
我想说的是,你很可能没有故意在计算中犯错误,因为它们是难以动态分析的函数,或者What kind of input would be the worst, for example
至于“为什么?”:
当谈到实际的个人运行时间(如您举的 0.877 秒示例)时,归结为我们自己的机器,每台计算机都有自己的幕后运行硬件,并非所有计算机生来都是一样的。
其次,当我们谈论运行时间复杂度时,我们会像使用 all_segments
函数一样删除低项值,您可以看到您甚至删除了一个负项,这在理论上可以帮助我们减少 ' 的数量操作”。
在很多情况下,有一些代码效率不高,以至于我们只有在满足特定条件时才费心执行,从而减少了运行时间。
最后也是最重要的是,当我们谈论分类时
算法成集合,例如我们正在谈论的O(n)
或O(nlogn)
渐近函数,我们需要放眼大局
当我们向算法提供大量数据时会发生什么,
我假设您没有检查,因为正如您所写,您只运行了 100 个城市。那可能
如果我们看看数以百万计的城市,情况会有所不同。
对于您的代码,我可以注意到多个部分合理地是导致运行时间出现这种“奇怪”差异的原因。首先,在ANN
代码中,更具体地说,在reverse_segment_if_better
函数中,我们并不总是反转列表,只有当某个语句被评估为真实值时。我们无法确定你给算法提供了什么样的输入,因此我只能想象它是否符合第二种算法。
此外,可能是我遗漏了一些东西(因为函数 reverse_segment_if_better
/ 我们无法查看函数 tour_length
或 distance
)但我不知道您是如何想到 O(n^4)
在结束了,好像在做O(n^3)
:
all_segments- no doubt it is O(n) - returning ~n/2 values
棘手的部分是分析reverse_segment_if_better
和alter_tour
- 反转只发生在i:j
因此说它有O(n)
并不完全正确 - 因为我们不反转整个之旅(至少,不是start, end
的每个值。
可以肯定地说,可能是没有渐近地检查非常大的数字,您提供了一个输入并且它对这个特定的算法很友好,或者T(n)
的最终形式不够严格。
【讨论】:
以上是关于TSP 算法的 BIG O 时间复杂度的主要内容,如果未能解决你的问题,请参考以下文章