Coursera Algorithm II PA5

这次作业题要求实现25个点的TSP问题

TSP的非递归动规解法本身就有一定的难度,但本题的重点却是内存优化,因为25点的 TSP 动规解法需要的内存较多

为了优化空间复杂度,这里引入了两个技巧:

1. Gosper’s hack

2. Combinadic

首先,还是要清楚了解TSP解法的状态转移方程,这里对状态转移方程做了详细的介绍,且带有伪代码

1. 我们用二进制来表示集合 S ,比如5个点的TSP问题,00111 表示集合S中有第1,2,3个点,00111 就表示大小为 3 的一个集合。

2. 从伪代码中,可以看出,我们需要枚举大小为 n 的集合 S,然后计算 C(S,k)

Gosper’s hack 能够以 o(1) 的时间计算出大小为 n 的下一个集合S,比如从 00111 -> 01011。

3. 对于 C(S,k),假如使用二进制来表示集合S,我们需要的空间是 int dp[x][y], 其中 x 为2^25, y 为 25,每一个int类型还需要4字节的空间,需要的总空间超过1G,这太高了

因此,我们需要引入另一种保存状态的机制:Combinatorial number system

用一个例子来说明组合数系统:假设对于5个点的TSP问题,我们要描述大小为 3 的所有集合(比如,00111),用朴素的二进制表示方法总是需要(2^5)的空间,但组合数系统用index来描述集合,如下表:

   Index           表示的集合
0 {0, 1, 2} 1 {0, 1, 3} 2 {0, 1, 4} 3 {0, 2, 3} 4 {0, 2, 4} 5 {0, 3, 4} 6 {1, 2, 3} 7 {1, 2, 4} 8 {1, 3, 4} 9 {2, 3, 4}

从上面的表中可以看出,我们仅需要 10 个数就能表示所有的集合,这样,对于5个点的TSP问题用 (2^4)即可完成大小为3的所有集合的标注。

那么,对于大小为 25 的TSP问题,我们可以节省多少空间呢?

朴素二进制表示方法 (2^25)*25*4,这个上面已经计算过了,大于1G

压缩后的方法         (c(25,13))*25*4, 其中 c(25,13)是从25个点中选取13 个点,这是使用压缩方法后需要内存大小的极值,经计算,不会超过300MB

我们已经看到状态压缩的内存优势,但不禁要问,如何从 01110 这样任意一个集合转化成对应的 index 呢?是时候让 Combinadic 登场了,这里链接提供了index, 集合的转换例子,比如10个点的TSP问题,0101001011对应的index是72, 计算公式是 C(8,5) + C(6,4) + C(3,3) + C(1,2) + C(0,1),第二个参数递减,第一个参数是不为0的那些位数

72   C(8,5) + C(6,4) + C(3,3) + C(1,2) + C(0,1)   0101001011        (8,6,3,1,0)

有了这两个技巧,25个点的TSP 问题就不用担心内存的问题了。

对于几百个点的TSP问题,用 local search 随机算法比较合适, youtube 上有一个视频,动态的展现出 local search 求解几百个点的tsp问题,很是震撼。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注