What exactly is the halting problem?

Sempre que as pessoas perguntam sobre o problema de parada no que se refere à programação, as pessoas respondem com "Se você acabou de adicionar um loop, você tem o programa de interrupção e, portanto, não pode automatizartarefa"

Faz sentido. Se o seu programa tem um loop infinito, então quando o seu programa está rodando, você não tem como saber se o programa ainda está processando a entrada, ou se está rodando infinitamente.

Mas algo disso parece contra-intuitivo. E se eu estivesse escrevendo um solucionador de problemas de interrupção, que usa o código-fonte como entrada.rascher@localhost$ ./haltingSolver source.c

Se meu código (source.c) for assim:

for (;;) {  /* infinite loop */  }

Parece que seria muito fácil para o meu programa ver isso. "Olhe o loop, e olhe para a condição. Se a condição é baseada apenas em literais, e sem variáveis, então você sempre sabe o resultado do loop. Se houver variáveis ​​(por exemplo, while (x <10)), veja se essas variáveis ​​são sempre modificadas. Se não, então você sempre sabe o resultado do loop. "

Concedido, essas verificações não seria trivial (cálculo de aritmética de ponteiro, etc), mas não parece impossível. por exemplo:

int x = 0
while (x < 10) {}

poderia ser detectado. juntamente com - embora não trivialmente:

int x = 0
while (x < 10)
{
   x++;
   if (x == 10)
   {
      x = 0
   }
}

Agora, e a entrada do usuário? Esse é o kicker, é isso que torna um programa imprevisível.

int x = 0;
while (x < 10) 
{
   scanf("%d", &x); /* ignoring infinite scanf loop oddities */
}

Agora meu programa pode dizer: "Se o usuário inserir um 10 ou mais, o programa será interrompido. Em todas as outras entradas, ele será repetido novamente".

O que significa que, mesmo com centenas de entradas, umadeveria ser capaz de listar as condições em que o programa irá parar. De fato, quando escrevo um programa, sempre me certifico de que alguém tenha a capacidade de terminá-lo! Eu não estou dizendo que a lista resultante de condições étrivial criar, mas não parece impossível para mim. Você poderia pegar a entrada do usuário, usá-la para calcular índices de ponteiro, etc - mas isso só aumenta o número de condições para garantir que o programa terminará, não torna impossível enumerá-las.

Então, qual é exatamente o problema da parada? O que não estou entendendo sobre a ideia de que não podemos escrever um problema para detectar loops infinitos? Ou, por que os "loops" são exemplos tão citados?

ATUALIZAR

Então, deixe-me mudar um pouco a questão: qual é o problema da paradacomo se aplica aos computadores? E então responderei a alguns dos comentários:

Muitas pessoas disseram que o programa deve ser capaz de lidar com "qualquer contribuição arbitrária". Mas nos computadores, nunca há entrada arbitrária. Se eu inserir apenas um único byte de dados, só tenho 2 ^ 8 entradas possíveis. Então, como exemplo:

int c = getchar()

switch (c) {
   case 'q':
      /* quit the program */
}

De repente, acabei de explicar todas as possibilidades. E sec tem o padrão de bits 0x71, faz uma coisa. Para todos os outros padrões, faz outra coisa. Mesmo um programa que aceita entrada arbitrária de strings nunca é realmente "arbitrário", já que os recursos são finitos, o que significa que enquanto a teoria de "arbitrária" se aplica ... não é exatamente um-para-um com a prática.

O outro exemplo que as pessoas citaram é este:

while (n != 1)
    if (n & 1 == 1) 
        n = 3 * n + 1;
    else 
        n /= 2;

Se n é um inteiro de 32 bits ... então eu posso dizer visualmente se isso irá ou não parar.

Eu acho que esta edição não está pedindo nada, mas o exemplo mais convincente que eu vi éeste:

Suponha que você tenha seu programa / método mágico para determinar que um programa é interrompido.

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
}

Agora vamos dizer que escrevemos um pequeno pedaço de código como ...

public static void Main(string[] args){
    string filename = Console.ReadLine(); //read in file to run from user
    if(DeterminesHalt(filename, args))
        for(;;);
    else
        return;
}

Então, para este exemplo, podemos escrever um programa para fazer exatamente o oposto do nosso método de parada mágica. Se de alguma forma determinarmos que um dado programa irá parar, nós apenas pulamos em um loop infinito; caso contrário, se determinarmos que o programa está em um loop infinito, terminamos o programa.

Então, novamente, se você intencionalmente escrever um programa que contenha um loop infinito ... "resolver o problema da parada" é meio discutível, não é?

questionAnswers(22)

yourAnswerToTheQuestion