解决图灵“停顿问题”的算法


23

“ Alan Turing于1936年证明,不存在解决所有可能的程序输入对暂停问题的通用算法”

我是否可以找到一种通用算法来解决某些可能的程序输入对的暂停问题?

我是否可以找到一种或多种编程语言,对于每种使用该语言的程序,我都可以决定该程序是否终止或永远运行?



3
CACM在5月发表了一篇非常有趣的文章:证明程序终止
Christoph Walesch 2011年

3
“一些可能的程序输入对的通用算法”-几乎是自相矛盾的。我想您想将自己限制为所有程序的无限子类吗?
拉斐尔

Answers:


25

我是否可以找到一种通用算法来解决某些可能的程序输入对的暂停问题?

是的,当然。例如,对于任何既不包含循环也不递归的程序,您可以编写一个算法返回“是,它终止”的算法,而对于任何while(true)肯定会到达且不包含循环的程序,则返回“否,它不终止”的算法一个break语句,以及其他所有内容的“ Dunno”。

我是否可以找到一种或多种编程语言,对于每种使用该语言的程序,我都可以决定该程序是否终止或永远运行?

如果该语言是图灵完备的话,不是。

但是,有一些非图灵完整的语言,例如CoqAgdaMicrosoft Dafny,其停顿问题是可以确定的(并且实际上是由它们各自的类型系统决定的,从而使它们成为全部语言(即,可能不会终止的程序不会编译))。


1
原始递归函数的类别是众所周知的“编程语言”,对于该问题,停顿问题是微不足道的。
拉斐尔

有几种“ 全部功能编程 ”语言,可证明所有程序都以该语言终止。
安德森·格林

3

我认为这里的所有答案都完全不正确。问题的答案是:假设程序打算停止,那么可以,您最好能够表明它停止了。如果您不能证明它容易停止,则应认为程序编写得很差,因此被质量控制部门拒绝。

是否实际可以编写合适的机器算法取决于输入的编程语言以及您的野心。一种编程语言的合理设计目标是使其易于证明终止。

如果语言是C ++,则您可能无法编写该工具,实际上,您不太可能使解析器运行,更不用说证明终止了。对于更好的结构化语言,您应该至少能够生成证明,或者至少使用某些假设来生成证明:在后一种情况下,工具应输出这些假设。一种类似的方法是将终止断言包含在语言中,并在工具会信任断言的复杂情况下使用它们。

最重要的是,似乎没有人似乎理解证明程序停止确实是可能的,因为打算编写此类停止程序的(优秀)程序员总是故意这样做,并且对它们为何终止并正确执行有一种心理印象:此类代码是有意为之的。这样写就可以清楚地看出它们已停止并且是正确的,并且如果合理的算法无法证明这一点(可能带有一些提示),则应拒绝该程序。

关键是:程序员不编写任何程序,因此不满足暂停定理的论断,结论也不适用。


4
我想完全是您完全错了。答案的第一段不适用于该问题,因为它询问的是算法-不是人类可以或不能证明的东西。其余的答案回答了问题的第一段,即算法是否可以证明某些程序的终止。前面的每个答案中的每个人都已经回答“是”。
sepp2k 2012年

3
您断言可以编写一种算法来证明以足够简单的图灵完备的语言终止每个编写良好的程序的说法完全是错误的。对于试图证明终止的所有可能算法,都存在无法解决该问题的每个程序都无法终止的问题。因此,除非您说解决该问题的每个程序都是按定义编写的(这很荒谬),否则这证明了您的观点。
sepp2k 2012年

1
@Sam如果有人问我一些代码是否暂停,我将看一下代码并尝试找出答案。但是我不是算法。是的,可以编写一种算法来检查程序是否暂停了许多程序。但这不是Yttrill所说的。Yttrill说,所有编写良好的程序都有可能。正如我在之前的评论中所说,除非您声称某些问题只能通过编写错误的程序来解决(这又太可笑了),否则这完全是错误的。
sepp2k 2012年

1
@Sam“在我看来,可以很容易地分析故意编写的用于暂停的程序的暂停条件”-如果是这种情况,为什么我们没有这样的工具?这并不是好像人们没有尝试。(罪魁祸首是方法重载:在编译时,您不知道将要执行的所有代码。)
拉斐尔

1
@Sam“是否存在无限循环”是一件很难的事情,即使对于现实世界的循环也是如此。当然,我被教导如何找到循环不变式,但这并不意味着在很多情况下我可以(轻松)找到一个。据我所知,这些天来猜测并证明是黄金标准。再次,如果有相当普遍的算法,我希望他们能够被纳入主要编译或集成开发环境(这执行一些琐碎的,语法检查)。您可以参考一个相当强大的算法吗?
拉斐尔

3

极好的(无意中的问题)问题。实际上,有一些停止检测程序可以在有限的输入集上成功。这是一个活跃的研究领域。它与(自动)定理证明区域有很强的联系。

但是,计算机科学似乎没有“有时”成功的“程序”的确切术语。“算法”一词通常用于总是停止的程序。

这个概念似乎与概率论算法截然不同,在概率论算法中,CS理论家坚持认为其成功有一定的已知或可计算的可能性。

有一个术语“ 算法”有时会使用,但显然是递归可枚举或不可计算的同义词。

因此,出于此目的,将它们称为quasialgorithms。这个概念不同于可决定与不可决定。

可能有人说不能比较拟算法。但实际上,这些拟算法似乎是自然的等级(部分排序)。假设一个拟算法可以检测到某些有限输入程序集X的停止。另一个B可以检测到集合Y的暂停。如果X ýX合适的子集ÿ然后比“更强大的” 一种XÿXÿXÿ一种

在CS中,到目前为止,“准算法层次结构”似乎只是非正式地研究。

它出现在繁忙的海狸研究[1]和PCP问题[2]中。实际上,对PCP的基于DNA的计算攻击可以看作是一种拟算法。[3] 在其他领域已经看到的定理证明[4]。

[1] 新千年攻击对繁忙的海狸问题

[2] Zhao (v2?)处理帖子的对应问题

[3] Kari等人使用DNA解决有界的邮政对应问题

[4] 通过Cook等人的Comm。证明程序终止。ACM的

(因此,实际上这是一个非常深层的问题,defn应该放在TCS.SE上……也许有人可以以适合并保留的方式重新询问它)


ps是一个证明拟定算法功能强大的令人印象深刻的例子,A​​CM指出,可以通过拟定算法来证明ackermanns函数可以中止,但是它比所有原始递归函数都大(不可计算)。
vzn 2012年

1
““算法”一词通常用于总是停止的程序。” -我不确定这是真的。周围有很多部分终止的算法(尤其是在验证中),我从来没有听说过有人不说“算法”。
拉斐尔

有“算法”的非正式用法。“部分终止”是可以的,但可能不是标准的。如前所述,似乎还没有一个标准化的术语。维基百科将一种算法定义为一种有效的方法,可以决定具有以下特征(1)总是给出一些答案,而不是从来没有给出答案;(2)始终给出正确答案,永不给出错误答案;(3)总是以有限的步骤完成,而不是无限的步骤;(4)处理所有类问题的实例。
vzn 2012年

然后在同一篇文章的后面,它说“对“有效方法”的进一步说明可能包括以下要求:当从该方法对其有效的类别之外给出问题时,该方法可以永远停止或循环而不会停止,但不能返回结果就好像是问题的答案。” 即它几乎与自己矛盾!显然,在关键问题上确实存在一些真正的困惑,并且现有术语并不严格。注意词“算法”是接近多于一个千年老左右&已经转移基本上....
VZN

的确是这样:传统意义可能是Wikipedia所说的“有效方法”(您引述的句子中没有矛盾;不过还不清楚)–人们没有想到不会终止的功能/算法(例如一些输入)。我认为,自1950年代以来,情况已经发生了变化。正如我所说,今天人们显然将部分终止方法称为“算法”。
拉斐尔

2

只要所讨论的编程语言足够复杂(即,如果图灵完整),那么总会有该语言的程序无法证明可以终止。

由于除最原始的语言以外的所有语言都是图灵完整的(只需要变量和条件之类的东西),因此您实际上只能构建很小的玩具语言来解决停顿问题。

编辑:根据评论,让我更加明确:您可以设计的任何语言(可以解决暂停问题)都必须是图灵不完整的。这排除了包含一组适当的基本成分(例如“变量,条件和跳转”或@ sepp2k所说的通用“ while”循环)的语言。

显然,有几种实用的“简单”语言(例如定理求解器,例如Coq和Agda)。如果这些满足您对“编程语言”的概念,则可以调查它们是否满足某种完整性,或者暂停问题对于他们而言是否可以解决。


3
“因为除了最原始的语言之外,所有其他语言都是图灵完整的(只需要像变量和条件之类的东西)”那是不对的。首先,您至少需要递归或某种形式的循环结构(它应该与while循环一样强大-一个简单的计数循环是不够的)。第二,我认为没有很多人会称呼诸如Coq或Agda之类的语言(它们是整体语言,因此并不完整),称为原始语言或玩具语言。
sepp2k 2011年

@ sepp2k:是的,是的。Peano算法也非常有用,并且图灵功能还不完善。我想一个简化的陈述。如果OP对该问题足够熟悉,则希望她能够填写技术细节。

3
在“足够复杂”和完成图灵之间存在巨大的差距。Coq确实很复杂,并且适用于非常广泛的实际任务。

1
@Kerrek SB好吧,使用图灵完备的语言可能会以证明终止的方式使用。如果您可以证明递归公式始终接近其终止条件(例如阶乘函数),则即使您无法处理每种类型的递归,也可以证明其终止。

@ArtB:当然,总有一些程序可以证明已终止。OP的第一个问题可能暗示了这一点,尽管我不确定我是否会完全遵循它。例如,您无法使用“通用算法”来确定任何给定的程序族是否终止,而相反,您可能可以构造一个受限的函数族,从而假设某个函数属于该族,则可以通过算法判断出它是否属于该族。终止。(不过,我不确定这个家庭是否可以平凡。我想可以,但是我不能举个例子。)

2

ŤŤ

这是很琐碎的。如果我们将停顿TM的任何ce子集与非停顿TM的任何ce子集进行并集,则结果将是可确定停顿问题的TM集合(如果第一台机器都接受TM,则并行运行两台机器停止,如果第二个接受,则机器不停止)。但是,这不会带来很多有趣的语言。

一种大号ØGŤ一世ËC中号


1

是的,您可以,但是我怀疑它会有用。您可能必须进行案例分析,然后才能查找最明显的案例。例如,您可以grep文件以获取代码while(true){}。如果文件具有该代码,它将永远不会终止^。更一般而言,您可以说没有循环或递归的程序将始终终止,并且在某些情况下您可以保证程序将终止或不终止,但是即使对于中型程序,这也将非常困难,并且在许多情况下将无法为您提供答案。

tl; dr:是的,但是您将无法对大多数有用的程序使用它。


^是的,从技术上讲,如果该代码不在代码路径上,或者仍然有其他线程可以终止,那么我在这里要指出一点。


4
您为什么认为Coq和Agda没用?您高估了图灵完备的价值。

我使用过Coq,但我的主张仍然存在,因为大多数商业软件都是用Java / C ++ / Ruby / C#编写的,因此我的主张是正确的。90%的人对写作感兴趣的那种程序不会受益。基本上,如果您不知道Coq / Agda等,您就不是目标市场。

5
我想说,在非图灵完备的语言子集中实施将使99%的现实世界程序受益。例如,您不会每天实现Ackermann函数。100%的CRUD不需要“真实”语言。数据处理几乎总是微不足道的。参见Terminator项目-他们甚至还在提供可能的C ++程序集的一部分,对于实际的东西(包括驱动程序和其他低级代码)而言,这些绰绰有余。

大多数现实世界项目都想重用用图灵完备的语言编写的库,并使用其IDE,调试器和教程。是的,您可以使用非图灵语言来完成任务,但是我无法想象有人会说“我想做X”,而我的回答是“使用Coq”。ps-感谢您向我介绍《终结者计划》

4
已经在非图灵完整的SQL中实现了不可思议的巨大业务逻辑。DSL和eDSL现在正在上升。因此,很快大多数业务应用程序程序员将忘记所有“通用”语言。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.