Computer science 停下来的问题到底是什么?

Computer science 停下来的问题到底是什么?,computer-science,halting-problem,Computer Science,Halting Problem,每当人们问起与编程有关的暂停问题时,人们的回答是“如果你只添加了一个循环,你就得到了暂停的程序,因此你无法自动完成任务” 有道理。如果您的程序有一个无限循环,那么当您的程序运行时,您无法知道该程序是否仍在处理输入,或者它是否只是无限循环 但其中一些似乎与直觉背道而驰。如果我写的是一个停顿的问题解决程序,它以源代码作为输入rascher@localhost$./haltingSolver source.c 如果我的代码(source.c)如下所示: for (;;) { /* infinite

每当人们问起与编程有关的暂停问题时,人们的回答是“如果你只添加了一个循环,你就得到了暂停的程序,因此你无法自动完成任务”

有道理。如果您的程序有一个无限循环,那么当您的程序运行时,您无法知道该程序是否仍在处理输入,或者它是否只是无限循环

但其中一些似乎与直觉背道而驰。如果我写的是一个停顿的问题解决程序,它以源代码作为输入<代码>rascher@localhost$./haltingSolver source.c

如果我的代码(source.c)如下所示:

for (;;) {  /* infinite loop */  }
看起来我的程序很容易看到这个。查看循环,然后查看条件。如果条件仅基于文本,而没有变量,则始终知道循环的结果。如果存在变量(例如while(x<10)),则查看这些变量是否曾经被修改过。如果没有,则始终知道循环的结果

诚然,这些检查并不琐碎(计算指针算术等),但它似乎并非不可能。例如:

int x = 0
while (x < 10) {}
突然间,我考虑了所有的可能性。如果
c
具有位模式0x71,那么它只做一件事。对于所有其他模式,它会执行其他操作。即使是接受任意字符串输入的程序也从来不是真正的“任意”程序,因为资源是有限的,这意味着虽然“任意”理论适用于。。。这种做法并不完全是一对一的

人们引用的另一个例子是:

while (n != 1)
    if (n & 1 == 1) 
        n = 3 * n + 1;
    else 
        n /= 2;
如果n是32位整数。。。然后我可以直观地告诉你这是否会停止

我猜这篇编辑没有提出任何问题,但我看到的最有说服力的例子是:

假设你有一个神奇的程序/方法来确定程序是否停止

public bool DeterminesHalt(string filename, string[] args){
    //runs whatever program you tell it do, passing any args
    //returns true if the program halts, false if it doesn't
}
public bool DeterminesHalt(string filename, string[] args){
    //runs whatever program you tell it do, passing any args
    //returns true if the program halts, false if it doesn't
}
现在让我们来写一小段代码,比如

public static void Main(string[] args){
    string filename = Console.ReadLine(); //read in file to run from user
    if(DeterminesHalt(filename, args))
        for(;;);
    else
        return;
}
public static void Main(string[] args){
    string filename = Console.ReadLine(); //read in file to run from user
    if(DeterminesHalt(filename, args))
        for(;;);
    else
        return;
}
因此,对于这个例子,我们可以编写一个程序来执行与我们神奇的停止方法完全相反的操作。如果我们以某种方式确定一个给定的程序将停止,我们只会跳入一个无限循环;否则,如果我们确定程序处于无限循环中,我们将结束程序


同样,如果你有意编写一个包含无限循环的程序。。。“解决停顿问题”是一种没有实际意义的问题,不是吗?

要解决停顿问题,你必须开发一种算法,可以确定任何任意的程序是否因任何任意输入而停顿,不仅仅是你的例子中相对简单的例子。

图灵的伟大例子是自我参照的——假设有一个程序可以检查另一个,并确定它是否会停止。将暂停程序检查器自身输入暂停程序检查器-它应该做什么?

您列出了一些简单的情况

现在,想想其他所有的案例

有无数种可能的场景,你必须把它们全部列出

当然,除非你能概括它


这就是停滞不前的问题所在。你是如何概括它的?

我建议读一下:,特别是为了理解为什么这个问题不能用算法来解决。

你的程序是如何解决这个问题的?

编辑(比原始答案晚得多):MarkCC最近写了一篇关于停止问题的文章,并给出了具体的例子

停顿问题基本上是一个问题 询问你是否能说出的正式方式 是否是任意程序 最终会停止

换句话说,你能写一篇文章吗 一个叫做停止预言的程序, 停止Oracle(程序、输入),其中 如果程序(输入)将 最终停止,然后返回 如果不是,那就错了

答案是:不,你不能

跟进关于停顿问题的输入是否相关或是转移注意力的问题:是的,输入很重要。此外,似乎有一些混淆,因为我看到“无限”被用在“任意”更正确的地方

实践示例:假设您在QA岗位上工作,您将编写一个暂停检查程序(又名oracle),该程序将确认,对于开发团队编写的任何任意程序(D)和最终用户提供的任何任意输入(I),当给定输入I时,程序D最终将停止

提示经理的声音:“呵呵,那些愚蠢的用户,让我们确保不管他们输入什么垃圾,我们的服务器任务永远不会以无休止的循环结束。让它这样吧,代码猴子!”

这似乎是个好主意,对吗?你不想让你的服务器挂起,对吧

停顿的问题告诉你的是,你被交给了一个无法解决的任务。相反,在这种特殊情况下,您需要为超过阈值时间的任务进行计划,并准备好取消它们

Mark使用代码而不是输入来说明问题:

def Deciever(i):
  oracle = i[0]
  in = i[1]
  if oracle(Deceiver, i):
    while True:
      continue
  else:
    return i
在我在评论中的讨论中,我采用了恶意输入操纵的方式来强制解决一个无法解决的问题。马克的例子要优雅得多,他用停滞不前的甲骨文打败了自己:

所以,欺骗者的输入实际上是 两个元素的列表:第一个 是一个被提议的停滞不前的预言家。这个 第二个是另一个输入。怎么回事 停滞不前的杀手是问神谕者: “你认为我会停止输入I吗?”。 如果神谕说:“是的,你会 “停止”,然后程序进入 无限循环。如果神谕说“不, 你不会停止“,然后它停止。所以不 不管神谕怎么说,都是错误的 错

换句话说,在没有作弊、重新设置输入格式、可数/不可数无穷大或任何其他干扰的情况下,马克编写了一段代码,可以击败任何停滞不前的oracle程序。您不能编写回答以下问题的
oracle
def Deciever(i):
  oracle = i[0]
  in = i[1]
  if oracle(Deceiver, i):
    while True:
      continue
  else:
    return i
public bool DeterminesHalt(string filename, string[] args){
    //runs whatever program you tell it do, passing any args
    //returns true if the program halts, false if it doesn't
}
public static void Main(string[] args){
    string filename = Console.ReadLine(); //read in file to run from user
    if(DeterminesHalt(filename, args))
        for(;;);
    else
        return;
}
collatz 1 = ()
collatz !n | odd n     = collatz (3 * n + 1)
           | otherwise = collatz (n `div` 2)
while (n != 1)
    if (n & 1 == 1) 
        n = 3 * n + 1;
    else 
        n /= 2;
int main()
{
  //Unbounded length integer
  Number i = 3;

  while(true)
  {
    //example: GetUniquePositiveDivisiors(6) = [1, 2, 3], ...(5) = 1, ...(10) = 1, 2, 5, etc.
    Number[] divisiors = GetUniquePositiveDivisiors(i);
    Number sum = 0;
    foreach(Number divisor in divisiors) sum += divisor;

    if(sum == i) break;

    i+=2;
  }
}
while x != 1 do
    if even(x)
        x = x/2
    else
        x = 3*x +1
f(n) is odd  -  f(n+1) = 3*f(n)+1
f(n) is even -  f(n+1) = f(n)/2
program_1 (input){
    loop forever
}
program_2 (input){
    halt
}
program_3 (input) {
    
    ...func definition...

    result = func(input)

    if result = 12345

    then loop forever

    else halt
}
func (input){
    ...definition of prime(k): return k-th prime number...
    
    result = prime(input)
    
    i = prime(input - 1)
    j = prime(input - 2)

    if(i mod j = 5)

    then loop forever

    else return result
}
for (x= 1; ; x++)
  for (y= 1; y <= x; y++)
    z= pow(x * x * x + y * y * y, 1./3.)
    if (z == int(z))
      stop;