Что именно является проблемой остановки? - PullRequest
52 голосов
/ 10 июля 2009

Когда люди спрашивают о проблеме остановки, связанной с программированием, люди отвечают: «Если вы просто добавите один цикл, у вас есть программа остановки, и поэтому вы не можете автоматизировать task »

Имеет смысл. Если ваша программа имеет бесконечный цикл, то, когда ваша программа работает, у вас нет возможности узнать, продолжает ли программа обрабатывать ввод, или она просто бесконечно зацикливается.

Но кое-что из этого кажется нелогичным. Что, если бы я писал программу решения проблем, которая принимает исходный код. rascher@localhost$ ./haltingSolver source.c

Если мой код (source.c) выглядит так:

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

Кажется, моей программе было бы довольно легко это увидеть. «Посмотрите цикл и посмотрите на условие. Если условие основано только на литералах, а не на переменных, то вы всегда знаете результат цикла. Если есть переменные (например, while (x <10)), посмотрите, эти переменные когда-либо изменяются. Если нет, то вы всегда знаете результат цикла. "</p>

Конечно, эти проверки не будут тривиальными (вычисление арифметики указателей и т. Д.), Но это не представляется невозможным. например:

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

может быть обнаружено. вместе с - хотя и не тривиально:

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

А как насчет ввода пользователя? Это кикер, это то, что делает программу непредсказуемой.

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

Теперь моя программа может сказать: «Если пользователь введет 10 или больше, программа остановится. На всех других входах она снова зациклится».

Это означает, что, даже с сотнями входов, один должен быть в состоянии перечислить условия, при которых программа остановится. Действительно, когда я пишу программу, я всегда проверяю, кто-то может ее прекратить! Я не говорю, что полученный список условий тривиален для создания, но он не кажется мне невозможным. Вы можете получить ввод от пользователя, использовать его для вычисления индексов указателей и т. Д., Но это только увеличивает количество условий, гарантирующих завершение программы, и не делает невозможным их перечисление.

Так в чем именно проблема остановки? Что я не понимаю в идее, что мы не можем написать задачу для обнаружения бесконечных циклов? Или почему "петли" такой часто цитируемый пример?

UPDATE

Итак, позвольте мне немного изменить вопрос: в чем заключается проблема с остановкой применительно к компьютерам? А потом я отвечу на некоторые комментарии:

Многие люди говорили, что программа должна быть в состоянии справиться с «любым произвольным вводом». Но в компьютерах нет никакого произвольного ввода. Если я введу только один байт данных, то у меня будет только 2 ^ 8 возможных входов. Итак, в качестве примера:

int c = getchar()

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

Внезапно я только что учел все возможности. Если 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 static void Main(string[] args){
    string filename = Console.ReadLine(); //read in file to run from user
    if(DeterminesHalt(filename, args))
        for(;;);
    else
        return;
}

Так что для этого примера мы можем написать программу, которая будет полностью противоположна нашей магической методике остановки. Если мы каким-то образом определим, что данная программа остановится, мы просто запрыгнем в бесконечный цикл; в противном случае, если мы определим, что программа находится в бесконечном цикле, мы завершаем программу.

Опять же, если вы намеренно напишите программу, которая содержит бесконечный цикл ... "решение проблемы остановки" - это спорный вопрос, не так ли?

Ответы [ 22 ]

2 голосов
/ 12 июля 2009

Это вариант проблемы остановки собаки , за исключением программ вместо собак и остановки вместо лая.

2 голосов
/ 10 июля 2009

Уже есть много хороших ответов, но я не видел, чтобы кто-то обращал внимание на тот факт, что в некотором роде сочетания теории и практичности проблема остановки действительно разрешима.

Итак, прежде всего, проблема останова - это в основном задача написания программы, которая берет любую произвольную вторую программу и определяет, остановится ли вторичная программа на произвольном вводе. Итак, вы говорите: «Да, эта программа остановится на этом входе» или «Нет, не будет». И на самом деле, это неразрешимо в общем случае (другие люди, кажется, уже предоставили доказательства этого) на машине Тьюринга. Реальная проблема заключается в том, что вы можете как-то выяснить, собирается ли что-то останавливаться, запустив его (просто подождите, пока он не остановится), но вы не можете действительно узнать, не остановится ли что-то, запустив это (вы просто продолжай ждать вечно).

Это проблема машины Тьюринга, которая по определению имеет бесконечное количество памяти и, следовательно, бесконечно много состояний. Однако наши компьютеры имеют только ограниченный объем памяти. На компьютере всего несколько битов. Поэтому, если вы можете каким-то образом отслеживать все предыдущие состояния (битовые конфигурации), которые вы видели во время работы программы, вы можете гарантировать, что ваша программа проверки никогда не войдет в бесконечный цикл. Если вторичная программа в конце концов останавливается, вы говорите: «Да, эта программа остановится на этом входе». Если вы видите одну и ту же битовую конфигурацию дважды, прежде чем она остановится, вы знаете «Нет, это не будет». Возможно, не имеет большого технического значения, но приятно знать, что во многих случаях действительно «сложные» проблемы, с которыми мы сталкиваемся, в теории сложнее, чем на практике.

2 голосов
/ 07 января 2018

Доказательство с другой точки зрения

Предположим, мы получили процессор с такими инструкциями, как mov, add, jmp, но без in или out.И у нас есть память.В отличие от других процессоров, у этого есть другой регистр, называемый paraReg .Этот регистр похож на файл, мы можем перемещать в него неограниченное количество контента, получать его размер, искать его в середине, удалять из него часть контента, что делается с помощью некоторых дополнительных инструкций.

Прежде чем мы начнем, давайте определимся с некоторыми словами. программа - это набор инструкций, представляющий собой строку.Перед запуском программы мы очищаем все регистры и память до нуля, кроме paraReg, который содержит параметр (строку), а затем помещаем программу в нулевую ячейку памяти и устанавливаем регистр ip в ноль. процесс - это когда программа работает.

Теперь проблема остановки может быть сформулирована так: для любой программы, называемой proObj (если она принимает параметр para0, мы добавляем инструкцию напервая строка: mov paraReg, para0), есть ли программа, которая принимает proObj в качестве параметра и может решить, будет ли proObj остановлен, когда proObj начнет работать на paraReg, установленном в ноль?

Предположим, мы получили такоепрограмма, которая называется p1.Затем мы можем создать другую программу с именем p2, которая принимает параметр para0.Через p1 мы можем сказать, остановится ли программа, содержимое которой para0, а ее параметр para0, остановится или нет. (Мы делаем это таким образом. Создайте программу, первая строка которой - [mov paraReg, para0], остальное - para0.Назовите эту программу pro0. Затем мы устанавливаем paraReg в pro0 и вызываем p1.) Если она остановится, мы позволим p2 войти в бесконечный цикл, в противном случае мы позволим p2 остановиться.

Если мы поместим p2 в paraReg и запустимp2, процесс остановится или нет?Если он останавливается из определения p2, мы знаем, что когда мы помещаем p2 в paraReg и запускаем p2, он не должен останавливаться;Точно так же, если он не останавливается, мы знаем, что если положить p2 в paraReg и запустить p2, он должен остановиться.Тогда мы можем сказать, что нет p2, и нет p1.

1 голос
/ 10 июля 2009

С Программирование Жемчуг , Джон Бентли

4,6 Проблемы

5. Докажите, что эта программа завершает работу, когда ее входные данные x являются положительным целым числом.

while x != 1 do
    if even(x)
        x = x/2
    else
        x = 3*x +1
1 голос
/ 10 июля 2009

Как ваша программа разрешает гипотезу Коллатца ?

1 голос
/ 10 июля 2009

Вы перечислили несколько простых случаев.

Теперь подумайте о всех остальных делах.

Существует бесконечное количество возможных сценариев, вам нужно перечислить их все.

Если, конечно, вы не сможете обобщить это.

Вот тут и возникает проблема остановки. Как вы ее обобщаете?

0 голосов
/ 10 июля 2009

Я бы предложил прочитать это: http://en.wikipedia.org/wiki/Halting_problem, особенно http://en.wikipedia.org/wiki/Halting_problem#Sketch_of_proof, чтобы понять, почему эта проблема не может быть решена алгоритмическим путем.

0 голосов
/ 26 августа 2009

Значение проблемы остановки не заключается в важности самой проблемы; напротив, автоматическое тестирование будет мало практического применения в программной инженерии (доказательство того, что остановка программы не доказывает, что она правильная , и в любом случае гипотетический алгоритм обеспечивает доказательство только для данного конечного ввода тогда как реальный разработчик программного обеспечения больше интересовался бы тестом для всех возможных конечных входных данных).

Скорее, проблема остановки была одной из первых, доказанных неразрешимой , что означает, что не существует алгоритма, который бы работал в общем случае. Другими словами, Тьюринг доказал более 70 лет назад, что есть некоторые проблемы, которые компьютеры не могут решить - не только потому, что правильный алгоритм еще не найден, но и потому, что такой алгоритм не может существовать логически.

0 голосов
/ 10 июля 2009

Точное определение проблемы заключается в том, что вам нужно написать программу, которая выполняет следующие действия: - принимает произвольную программу - определяет, останавливает ли программа заданный произвольный конечный ввод в программу

Тем не менее, это действительно высокая планка. Существует много частичных решений проблемы остановки, но нет общего решения. Что еще хуже, даже найти программы, которые частично решают проблему остановки, как известно, трудно:

BBC h2g2 статья о проблеме остановки

Если вы действительно решили проблему остановки, то для вас есть такие сайты, как rentacoder.com. Несколько месяцев назад на одном из них было сообщение от пользователя ATuring, предложившего контракт для решения проблемы остановки. :)

0 голосов
/ 10 июля 2009

Возможно, вам будет полезно рассмотреть историю о парне, который косит газон любого, кто не косит свой собственный газон, и спросить себя, действительно ли он косит свой собственный газон.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...