转载 王垠谈“P=NP?”

P=NP?” 通常被认为是计算机科学最重要的问题。有一个叫 Clay Math 的研究所,甚至悬赏 100 万美元给解决它的人。可是我今天要告诉你的是,这个问题其实是不存在的,它根本不需要解决。

我并不是第一个这样认为的人。在很早的时候,就有个数学家毫不客气的指出,P=NP? 是个愚蠢的问题,并且为了嘲笑它,专门在4月1号写了一篇“论文”,称自己证明了 P=NP。我身边有一些非常聪明的人,他们基本也都不把这问题当回事。如果我对他们讲这些东西,恐怕已经是老生常谈,所以我只是在这里科普一下。

首先,你要搞清楚什么是“P=NP?” 为此,你必须先了解一下什么是“算法复杂度”。为此,你又必须先了解什么是“算法”。

你可以简单的把“算法”想象成一台机器,就跟绞肉机似的。你给它一些“输入”,它就给你一些“输出”。比如,绞肉机的输入是肉末,输出是肉渣。牛的 输入是草,输出是奶(或者牛米田共)。“加法器”的输入是两个整数,输出是这两个整数的和。“算法理论”所讨论的问题,就是如何设计这些机器,让它们更加 有效的工作。就像是说如何培育出优质的奶牛,吃进相同数量的草,更快的产出更多的奶。

世界上的计算问题,都需要“算法”经过一定时间的工作(也叫“计算”),才能得到结果。计算所需要的时间,往往跟“输入”的大小有关系。你的牛吃越是多的草,它就需要越是长时间才能把它们都变成奶。这种草和奶的转换速度,通常被叫做“算法复杂度”。

算法复杂度通常被表示为一个函数 f(n),其中 n 是输入的大小。比如,如果你的算法复杂度为 n2,那么当输入10个东西的时候,它需要 100 个单元的时间才能完成计算。当输入 100 个东西的时候,它需要 10000 个单元的时间才能完成。当输入 1000 个数据的时候,它需要 1000000 个单元的时间。简单吧。

所谓的“P时间”,就是“Polynomial time”,多项式时间。简而言之,就是说这个复杂度函数 f(n) 是一个多项式。多项式你该知道是什么吧?不知道的话就翻一下中学数学课本。

“P=NP?”中的“P”,就是指所有这些复杂度为多项式的算法的“集合”,也就是“所有”的复杂度为多项式的算法。为了简要的描述以下的内容,我定义一些术语:

“f(n) 时间算法” = “能够在 f(n) 时间之内,解决某个问题的算法”

当 f(n) 是个多项式(比如 n2)的时候,这就是“多项式时间算法”(P 时间算法)。当 f(n) 是个指数函数(比如 2n)的时候,这就是“指数时间算法”(EXPTIME 算法)。很多人认为 NP 问题就是需要指数时间的问题,而 NP 跟 EXPTIME,其实是风马牛不相及的。很显然,P 不等于 EXPTIME,但是 P 是否等于 NP,却没有一个结论。

现在我来解释一下什么是 NP。通常的计算机,都是确定性(deterministic)的。它们在同一个时刻,只有一种行为。如果用程序来表示,那么它们遇到一个条件判断(分支)的时候,只能一次探索其中一条路径。比如:

if (x == 0) {

    one();

} else {

    two();

}

在这里,根据 x 的值是否为零,one() 和 two() 这两个操作,只有一个会发生。

然而,有人幻想出来一种机器,叫做“非确定性计算机”(nondeterministic computer),它可以同时运行这程序的两个分支,one() 和 two()。这有什么用处呢?它的用处就在于,当你不知道 x 的大小的时候,根据 one() 和 two() 是否“运行成功”,你可以推断出 x 是否为零。

这种非确定性的计算机,在“计算理论”里面叫做“非确定性图灵机”。与之相对的就是“确定性图灵机”,也就是通常所谓的“计算机”。其实,“图灵机”这名字在这里完全无关紧要。你只需要知道,非确定性的计算机,可以同时探索多种可能性。

这不是普通的“并行计算”,因为每当遇到一个分支点,非确定性计算机就会产生新的计算单元,用以同时探索这些路径。这机器就像有“分身术”一样。当 这种分支点存在于循环(或者递归)里面的时候,它就会反复的产生新的计算单元,新的计算单元又产生更多的计算单元,就跟细胞分裂一样。一般的计算机都没有 这种“超能力”,它们只有固定数目的计算单元。所以他们只能先探索一条路径,失败之后,再回过头来探索另外一条。所以,它们似乎要多花一些时间才能得到结 果。

到这里,基本的概念都有了定义,于是我们可以圆满的给出 P 和 NP 的定义。P 和 NP 是这样两个“问题的集合”:

P = “确定性计算机”能够在“多项式时间”解决的所有问题

NP = “非确定性计算机”能够在“多项式时间”解决的所有问题

(注意它们的区别,仅在于“确定性”或者是“非确定性”。)

定义完毕。现在回到对“P=NP?”问题的讨论。

“P=NP?”问题的目标,就是想要知道 P 和 NP 这两个集合是否相等。为了证明两个集合(A 和 B)相等,一般都要证明两个方向:

1. A 包含 B

2. B 包含 A

你也许已经看出来了,NP 肯定包含了 P。因为任何一个非确定性机器,都能被当成一个确定性的机器来用。你只要不使用它的“超能力”,在每个分支点只探索一条路径就行。所以“P=NP?”问题 的关键,就在于 P 是否也包含了 NP。也就是说,如果只使用确定性计算机,能否在多项式时间之内,解决所有非确定性计算机能在多项式时间内解决的问题。

我们来细看一下什么是多项式时间(Polynomial time)。我们都知道,n2 是多项式,n1000000 也是多项式。多项式与多项式之间,却有天壤之别。把解决问题所需要的时间,用“多项式”这么笼统的概念来描述,其实是非常不准确的做法。在实际的大规模应用中,n2 的算法都嫌慢。能找到“多项式时间”的算法,根本不能说明任何问题。

对此,理论家们喜欢说,就算再大的多项式(比如 n1000000),也不能和再小的指数函数(比如 1.0001n)相比。因为总是“存在”一个 M,当 n > M 的时候,1.0001n 会超过 n1000000。 可是问题的关键,却不在于 M 的“存在”,而在于它的“大小”。如果你的输入必须达到天文数字才能让指数函数超过多项式的话,那么还不如就用指数复杂度的算法。所以,“P=NP?”这 问题的错误就在于,它并没有针对我们的实际需要,而是首先假设了我们有“无穷大”的输入,有“无穷多”的时间和耐心,可以让多项式时间的算法“最终”得到 优势。“无穷”和“最终”,就是理论家们的杀手锏。

为了显示这个问题,我们可以画一个坐标曲线,来比较一下 n1000000 与 2n,并且解出它们相等时的 n。我不用 1.0001n 来比,免得有人说我不公平。我喜欢偷懒,经常用 Mathematica 来解决这些算式。下面就是我用它得出的结果和曲线图:

转载 王垠谈“P=NP?”

你看到了,当 1 < n < 24549200 的时候,我们都有 2n < n1000000 (n1000000 那根曲线,一超过1就冲上天去了)。所以只要输入没有达到2千万这个量级,2n 的算法都比 n1000000 的算法快。

n1000000 也许不说明问题,但是“多项式”的范围实在太大了。n10100 ,n1010100,…… 都是多项式。实际上,只要 c 是个常数,任何常数,nc 就是个多项式。

你能想象 n 需要多大,2n 才能超过 n10100 吗?当 n=2 的时候,n10100 就是 210100。你也许已经意识到,这个数相当于 2n 复杂度的算法,接受了 10100 个输入。如果你知道 10100(1 的后面跟100个0)已经大于宇宙中基本粒子的数目,你也许就会意识到,这是在计算宇宙里所有的粒子的“幂集”(power set),也就是在枚举宇宙里所有粒子的所有组合。通俗一点说,就是在枚举宇宙里所有可能出现的物体!当任何超级电脑完成这个任务的时候,宇宙恐怕都已经 不存在了。况且这个计算是根本无法完成的,因为即使每个粒子可以提供一次计数所需要的能量,你会在还没有数到 10100 的时候就用光宇宙里所有的能量。最后,因为这两个 n 是同步的,所以当 2n 的输入是 10100 的时候,n10100 等于 (10100)10100。所以即使枚举了宇宙里所有可能出现的物体,2n 仍然远远落后于 n10100

你也许发现了,其实上面的论述根本没必要用 n10100 这么大的多项式,只要用一个很大的常数(比如 10100)就够了,因为常数也算是多项式。使用多项式的原因,只是想演示一下多项式可以有多大。

当你抓住这个要害的时候,理论家们往往又说,你给的这个例子太离谱了,解决了“P=NP?”,不管是肯定的还是否定的结论都会带来好处:

1. 如果 P 等于 NP,那么它能够帮助我们找到“快速”的多项式算法,

2. 如果 P 不等于 NP,那么我们知道多项式算法“不存在”,从而避免了不必要的工作。

而这两个结论,其实都有致命的逻辑错误。

让我们先来看看第一点,“如果 P 等于 NP,能够帮助我们找到快速的多项式算法”。这其实是一个偷换概念的诡辩,“P=NP?”的“目标”,与理论家们所声称的“意义”,其实在逻辑上是不一致 的。你需要特别精确理解的一点是,这个问题的定义从头到尾就没有提到“快速”两个字。它只关心“能否”够找到多项式时间算法,而不是能否找到“快速的”多 项式时间算法。少了“快速的”三个字,就是说可以是“任意多项式”,也就是说完全可以是像 n10100 这样的。所以,“P=NP?”的目标(证明“能否找到多项式时间算法来解决所有的 NP 问题”),其实对于“找到快速的多项式算法”,一点用都没有。

这是“存在性问题”与“数值性问题”的区别。就好像是一个人说:“我是有钱人。” 等到大家对他刮目相看的时候,他又说:“我有一块钱!”这是很基本的逻辑诡辩,却有很多人被它迷糊了。

再来看看第二点,“如果 P 不等于 NP,那么我们知道多项式算法不存在,从而避免不必要的工作”。如果 P 不等于 NP,我们对这个问题的定义做一个“逻辑逆”,得到:“并不是对所有的 NP 问题,我们都能找到多项式时间的算法。” 也就是说:“有些 NP 问题找不到多项式时间的算法。” 注意这里说的是“有些”(some),而不是“所有”(all)。换句话说,对于有些 NP 问题,就算 P 不等于 NP,我们仍然“有可能”找到多项式的算法。有可能就有希望,有希望就有人会耗费时间去寻找它。既然没能完全消灭为 NP 问题找到多项式算法的“希望”,这结论又如何能“避免不必要的工作”?误解了这一点的人,就是因为没有搞清楚,“所有”的逻辑逆是“有些”。他们错误地认 为“P 不等于 NP”的含义是“所有的 NP 问题都不能找到多项式时间算法。” 如果真是这样的话,那这结论可能还有一点用处。

(深入的内容:为了通俗易懂,我并没有在上面这段深入讨论 NP-Complete。不理解“NP-Complete 等价性”的人,可以跳过现在这段话。上面所说的,即使 P 不等于 NP,也有可能找到多项式时间算法的 NP 问题,一定不会是 NP-Complete 问题。因为 NP-Complete 问题的结论,全都可以在多项式时间互相转换。只要有一个 NP-Complete 问题存在多项式时间算法,所有的 NP-Complete 问题都会有多项式时间算法。可是有人却证明了,如果 P 不等于 NP,那么 NP 问题里面就存在一些问题,既不是 P 也不是 NP-Complete。所以,即使 P 不等于 NP,这些问题仍然有可能找到多项式时间算法。所以第二点的逻辑错误其实真正在于,错误的假设了 NP 问题里面除了 P 就是 NP-Complete。)

这第二点里面,除了关键的逻辑错误,其实还有跟第一点同样的问题。那就是它首先就假设了在任何情况下,多项式时间算法都比其他复杂度的算法好。它下 意识里觉得,所有人都“希望”得到多项式时间算法。所以它才会觉得,如果能消灭这种“希望”,就会省掉这些人不必要的烦恼。但是其实正确的做法,并不是一 味去寻找多项式算法,而是找到多个算法之后,画出像我所示的曲线图,根据不同的输入大小,资源限制,计算目标,实现难度,经过分析比较,因地制宜的选择最 好的算法。

我早期对算法的研究告诉我一个经验,如果花了很多功夫,仍然找不到一个简单而快速的多项式算法,那么快速的多项式算法往往不存在。当然,你可以花更 多功夫,经过长篇累牍的证明各种上限下限,找到很复杂的多项式算法,但是这些算法的实际效率,往往还不如很简单的指数时间算法。另外,这里讲的算法复杂度 都是指最坏情况下的复杂度。如果你的算法能够随输入的改变而调整自己,或者加入一些随机性或者 heuristics,往往可以达到意想不到的效果。

所以我们看到了,不管 P 是否等于 NP,得到的结论都不能产生理论家们所期望的效果。所以,“P=NP?”根本就不需要答案,因为它是一个不存在的问题。

————————————————————————————————

以下为张志强的评论:

王垠写了不少文章,其中有一些说了较多别人做得如何地差,对自己的评价则相当高(我和Google的故事这篇文章是一篇典型,几篇退学的文章类 似)。但之前我并不太了解他工作的领域,并不清楚这哥们的真实水平。但这几天他评论的P vs NP问题,恰好是我也熟悉的领域。其评论让我不吐不快,并且认为他太刚愎自用,他的三次退学也绝不是偶然。

王垠最近发表了一篇文章,名字叫做《解决问题和消灭问题》,大意是很多难题都是“人造”的,而不是“必然”的。这些问题根本不是问题,不需要去解决,而应该直接忽略或者说消灭它。

这个大而广的结论具有政治正确性,你不可能去驳斥。但王垠同学居然用“P vs NP”举例,认为“P vs NP”就是一个这样没有任何意义的问题。

后面王垠又发表了一篇文章《谈“P=NP?”》,里面主要两个论点是:

  • “P=NP?”这问题的错误就在于,它并没有针对我们的实际需要,而是首先假设了我们有“无穷大”的输入,有“无穷多”的时间和耐心,可以让多项式时间的算法“最终”得到优势。“无穷”和“最终”,就是理论家们的杀手锏。 王垠举的多项式的例子是 甚至
  • “P=NP?”只关心是否“能够找到多项式时间算法”,而不关心是否“能够找到快速的多项式时间算法”。少了“快速的”三个字,也就是说这个多项式算法的复杂度,完全可以是像  这样的。所以“P=NP?”的目标,也就是证明是否“能够找到多项式时间算法来解决所有的 NP 问题”,其实对于“找到快速的多项式算法”,一点用都没有。

这两个论点非常有迷惑性,但事实上:

  1. 如果能证明N=NP,对于NP-Hard问题找到的算法的确可以像 没有任何实际意义,但也可能是 。比如素数判定问题在2002年才被找出多项式算法,它的复杂性并未高的离谱,最终改进的结果是 。先找到一个解,才能继续谈去优化这个解。
  2. 事实上,如果能证明N=NP,简单的多项式算法更有可能。由于在NP问题之间存在归约关系,所有NP问题都可以归约到一个3-SAT问 题,只要 3-SAT问题存在一个比较快的解法,其它NP-Hard问题都有一个类似的较快的解法。王垠举的多项式的次数显示他对这个问题缺乏最基本的了解。
  3. N^6和2^N的分界线低于30。
  4. 另一方面,多数理论学家都相信“P!=NP",即NP问题不存在多项式算法,即使 级别的算法都没有。而王垠似乎断定P=NP。

王垠介绍P和NP问题为确定型图灵机和非确定型图灵机可在多项式时间内解决的问题,这只是一种形式上的定义。更本质以及更容易理解的定义应该是下面这个:

  1. P是指普通计算机可以快速求解的问题(的集合),这里快速求解指多项式时间内。
  2. NP问题指普通计算机可以快速验证解的正确性的问题。

举个例子,比如说大数分解问题,即要将一个很大的数分解为质因子的乘积。这个问题目前还没找到多项式算法,所以无法确定是否属于P。

但如果你一旦知道大数分解的结果,然后判断这个结果是否正确,则是一件非常简单的事情,只需要把质因子乘起来看看是否等于大数即可。所以大数分解就是一个NP问题。

从这个角度看,NP的思想已经不限于算法领域,它有更深层次的哲学含义。比如我们平时读论文时,验证别人证明方法往往比较容易,那么是否有一种思考的方法,能快速求解全天下所有问题呢?其它一些有趣的讨论见What if P = NP?。

所以我认为P vs NP问题是数学领域有史以来最重要的问题之一,它成为Clay研究所公布的千禧七大问题之一绝对是实至名归。

如果王垠能从概率算法和近似算法(这两个是更实用的算法,但其复杂性也是理论界存在多年的疑难问题)这类实用算法的角度来攻击P vs NP,我会更尊重他。

你可能感兴趣的:(转载 王垠谈“P=NP?”)