不可解问题(Undecidable Decision Problem
)指的是这样一种问题:它无论如何也不可能有一个正确的算法来解决。虽然不可思议,但这种问题被证明确实是存在的。图灵在1936
年提出了第一个不可解问题的实例:The Halting Problem
。
The Halting Problem
是指,输入一段程序代码和一个针对此程序的输入,能否编程判断运行这个程序后程序是否会终止。这个问题的答案是否定的,也就是说不可能有一种算法可以正确判断一个指定的程序运行后,给予指定的输入,程序最后出不出得来。换句话说,The Halting Problem
是一个不可解问题。
假设我们某一天真做出了这么一个极度聪明的万能算法(就叫God_algo
吧),你只要给它一段程序(二进制描述),再给它这段程序的输入,它就能告诉你这段程序在这个输入上会不会结束(停机)。我们来编写一下这个算法:
bool God_algo ( char *program, char *input ) {
if ( <program> halts on <input> ) {
return true;
}
return false;
}
这里假设if
的判断语句里面是天才思考的结晶,它能够像上帝一样洞察一切程序的宿命。现在从这个God_algo
出发,导出一个新的算法:
bool Satan_algo ( char *program ) {
if ( God_algo ( program, program ) ) {
while ( 1 ); /* loop forever! */
return false; /* can never get here! */
} else {
return true;
}
}
正如它的名字所暗示的那样,这个算法便是一切邪恶的根源了。当我们把这个算法运用到它自身身上时,会发生什么呢?
Satan_algo ( Satan_algo );
我们来分析一下这行简单的调用:显然Satan_algo(Satan_algo)
要么能够运行结束返回(停机),要么不能返回(loop forever
)。如果它能够结束,那么Santa_algo
算法里面的那个if
判断就会成立(因为God_algo(Santa_algo, Santa_algo
)将会返回true
),从而程序便进入那个包含一个无穷循环while(1);
的if
分支,于是这个Satan_algo(Satan_algo)
调用便永远不会返回(结束)了。如果不能结束(停机),则if
判断就会失败,从而选择另一个if
分支并返回false
,即Satan_algo(Satan_algo)
又能够返回(停机)。可以得到如下结论:
-
Satan_algo
能够停机 =>Satan_algo(Satan_algo)
不能停机。 -
Satan_algo
不能停机 =>Satan_algo(Satan_algo)
能够停机。
于是得到矛盾的结果。