В чем именно заключается проблема остановки?

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

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

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

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

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

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

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

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 или больше, программа останавливается. При всех остальных вводах она повторяется снова».

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

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

ОБНОВЛЕНИЕ

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

Многие говорят, что программа должна иметь возможность обрабатывать «любой произвольный ввод». Но в компьютерах никогда не бывает произвольного ввода. Если я ввожу только один байт данных, то у меня есть только 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;
}

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

С другой стороны, если вы намеренно напишете программу, содержащую бесконечный цикл ... «решение проблемы остановки» - это своего рода спорный вопрос, не так ли?


person poundifdef    schedule 10.07.2009    source источник
comment
Напишите программу, которая завершается только тогда, когда находит решение открытого вопроса; например, первое совершенное нечетное число. Теперь примените вашу технику решения проблемы остановки к этой программе. Проблема остановки не в циклах, а в теории вычислений.   -  person Kevin Montrose    schedule 10.07.2009
comment
@Kevin, а еще лучше, возьмем на вход программу, вычисляющую последнее совершенное число. Он может остановиться, а может и нет. Не было доказано, что серия бесконечна или конечна.   -  person Bob Cross    schedule 11.07.2009
comment
Вы не должны использовать программы на языке C для демонстрации задач теории вычислений. Важно выбрать очень простую модель, чтобы упростить понимание. С реальными языками программирования можно составить так много странных случаев, что их становится почти невозможно понять. Этого не происходит с машинами Тьюринга, WHILE-программами или µ-рекурсивными функциями. И, в конце концов, они столь же эффективны, как и любой нормальный язык программирования.   -  person pmr    schedule 12.07.2009
comment
Суть вашего последнего примера (с методом DeterminesHalt) заключается в том, что ваш метод в этом случае является НЕПРАВИЛЬНЫМ. Например, если вы запустите Main на Main.java, это будет равносильно тому, чтобы сказать, что эта программа останавливается, если она выполняется навсегда, и запускается вечно, если она останавливается. Парадокс! Будьте осторожны: ваш компьютер может расплавиться.   -  person agorenst    schedule 26.08.2009
comment
Много вопросов и ни одного, который действительно отвечал бы на исходный вопрос.   -  person doubleOrt    schedule 11.06.2018
comment
@Kevin Montrose. Но если бы программа могла проанализировать, что входные данные - это программа, предназначенная для решения открытой проблемы, она могла бы остановиться без ответа.   -  person rsonx    schedule 14.06.2021


Ответы (25)


ИЗМЕНИТЬ (намного позже, чем исходный ответ): MarkCC из Хорошая математика, плохая математика недавно написал отличное обсуждение проблемы остановки с конкретными примерами.

Проблема остановки - это, по сути, формальный способ спросить, можете ли вы сказать, остановится ли произвольная программа в конечном итоге.

Другими словами, можете ли вы написать программу, называемую останавливающимся оракулом, HaltingOracle (программа, ввод), которая возвращает истину, если программа (ввод) в конечном итоге остановится, и которая возвращает ложь, если нет?

Ответ: нет, нельзя.

Ответ на вопросы о том, является ли исходная информация для проблемы остановки актуальной или отвлекающим маневром: да, входная информация важна. Кроме того, кажется, есть некоторая путаница в том, что я вижу, что слово «бесконечный» используется там, где более правильным является «произвольный».

Практический пример: представьте, что вы работаете в должности QA и должны написать программу проверки остановки (также известную как оракул), которая подтвердит это для любой произвольной программы, написанной команда разработчиков (D) и любой произвольный ввод, предоставленный конечным пользователем (I), программа D в конечном итоге остановится при получении ввода I.

Голос менеджера сигналов: «Хо-хо, эти тупые пользователи, давайте позаботимся о том, чтобы, какой бы мусор они не набирали, наши серверные задачи никогда не заканчиваются бесконечным циклом. Сделайте это так, кодовая обезьяна!»

Это кажется отличной идеей, правда? Вы же не хотите, чтобы ваш сервер завис, верно?

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

Марк использует код вместо ввода, чтобы проиллюстрировать проблему:

def Deciever(i):
  oracle = i[0]
  in = i[1]
  if oracle(Deceiver, i):
    while True:
      continue
  else:
    return i

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

Итак, ввод в Deceiver на самом деле представляет собой список из двух элементов: первый - это предполагаемый останавливающийся оракул. Второй - еще один ввод. Остановившийся убийца спрашивает Оракула: «Как ты думаешь, я остановлюсь, чтобы ввести i?». Если оракул говорит: «Да, вы остановитесь», программа переходит в бесконечный цикл. Если оракул говорит: «Нет, ты не остановишься», он останавливается. Итак, что бы ни говорил оракул, это неправильно.

Другими словами, без обмана, переформатирования входных данных, счетных / бесчисленных бесконечностей или каких-либо других отвлекающих факторов, Марк написал фрагмент кода, который может победить любую останавливающуюся программу оракула. Вы не можете написать oracle, который отвечает на вопрос, останавливается ли Deceiver.

Исходный ответ:

Из замечательной Википедии:

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

Алан Тьюринг доказал в 1936 году, что не может существовать общий алгоритм для решения проблемы остановки для всех возможных пар программа-ввод. Мы говорим, что проблема остановки неразрешима для машин Тьюринга. Коупленд (2004) приписывает настоящую проблему прерывания термина Мартину Дэвису.

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

Отметим также, что машины Тьюринга являются основой эффективных моделей вычислимости. Иными словами, все, что вы делаете на современных компьютерных языках, можно сопоставить с архетипическими машинами Тьюринга. В результате проблема остановки неразрешима на любом полезном современном языке.

person Bob Cross    schedule 10.07.2009
comment
Тот факт, что у вас нет контроля над вводом в программу, на самом деле не имеет большого значения, потому что для любой пары (программа, ввод) (P, I) вы можете тривиально создать новую программу Q, которая принимает нет ввода и делает в точности то же, что P делает с I. (И спросите, останавливается ли Q). - person ShreevatsaR; 13.07.2009
comment
@ShreevatsaR, хотя это правда, что вы можете создать единственную программу Q, которая имитирует единственную пару (P, I), это не имеет значения. Вы не упустили проблему. Если вы будете следовать своей стратегии, то теперь вы столкнетесь с написанием возможных программ в формате PXI (P cross I) Q, где I - несчетное бесконечное множество (вы не только не можете контролировать вводимые мной данные, вы даже не можете их перечислить. возможности). Сопряжение программы и ввода очень важно. - person Bob Cross; 13.07.2009
comment
Нет, множество всех PxI по-прежнему счетно бесконечно. (Декартово произведение любых двух счетных множеств счетно!) Я не говорю, что проблема тривиальна, напротив, я объяснял, что входная часть не делает проблему сложной; даже простое решение, невозможно ли решить программы, не требующие остановки ввода. - person ShreevatsaR; 13.07.2009
comment
Вы считаете, что вводимые данные можно считать исчисляемыми? Что, если я введу действительное число? Затем будет применена диагонализация Кантора, что сделает набор допустимых входных данных несчетным бесконечным: en.wikipedia.org/wiki / Cantor% 27s_diagonal_argument Тем не менее, я думаю, что вы могли бы написать программу с жестко запрограммированным вводом, чтобы отвлекать внимание. Тем не менее, если вы считаете, что этот момент стоит подчеркнуть (даже если вы уберете ввод, это все равно ошибка), я добавлю его к ответу. - person Bob Cross; 13.07.2009
comment
Входными данными для машины Тьюринга является последовательность символов на ее входной ленте, и, таким образом, они являются счетными. (Для программы, независимо от того, является ли ее ввод последовательностью цифр или чем-то еще, набор всех определяемых чисел по-прежнему является счетным.) Итак, что касается проблемы остановки, ввод является счетным. (Существует модель реальных вычислений, представленная Блюмом-Шубом-Смейлом, но я не знаком с ней и, похоже, мало используется.) Я не думаю, что этот момент стоит подчеркнуть, просто пытаясь избежать мысли, что если я пишу только программы, которые не принимают ввод, я могу решить, останавливаются ли они :-) - person ShreevatsaR; 14.07.2009
comment
@ShreevatsaR, я согласен с тем, что любой вклад можно подсчитать. Общего набора возможных входов нет. Однако я согласен с вами в том, что этого недостаточно, чтобы сказать: эй, а что, если я жестко закодирую ввод? Тогда я буду на Easy Street! ;-) - person Bob Cross; 15.07.2009
comment
В любом случае ввод - это отвлекающий маневр, поскольку для любого конечного набора вводов вы можете просто воссоздать их с помощью функции-обертки. (Для программ, которые имеют дело с бесконечной последовательностью входных данных, таких как серверы, вам нужна другая формулировка проблемы, но в любом случае она основывается на работе с конечными функциями / алгоритмами.) - person Donal Fellows; 08.10.2010
comment
@Donal, ввод определенно не отвлекающий маневр. См. Правки и обсуждение Марка, чтобы узнать, почему это так. - person Bob Cross; 08.10.2010
comment
@ Боб: О, но это отвлекающий маневр. Это отвлекающий маневр, потому что вы переписываете программу, которая действительно принимает входные данные, с точки зрения той, которая не принимает. Это даже не сложно переписать. Это также очень второстепенный момент (FWIW, легче понять, что происходит, когда есть подпрограммы, которые принимают входные данные). - person Donal Fellows; 08.10.2010
comment
@Donal, нет, ты не можешь. Вы предполагаете априорное знание. Вы не знаете, какой вклад я собираюсь предоставить заранее, и у меня есть полная свобода ввода. После того, как я предоставлю ввод, вы можете переписать программу, как если бы этот ввод был заранее заданной константой, но это было бы пустой тратой времени. На этом этапе вы не решаете общую проблему, вы пытаетесь решить один конкретный пример. Это эквивалентно тому, что если я уже знаю ответ, я могу доказать его правильность. - person Bob Cross; 08.10.2010
comment
Переменная in установлена, но никогда не используется. - person Jonas Elfström; 13.10.2011
comment
@ JonasElfström, SIC. Цитата является точным воспроизведением оригинала. Марк очень доступен для исправлений, если вы хотите обсудить с ним эту мысль. - person Bob Cross; 13.10.2011
comment
Проблема остановки говорит вам о том, что перед вами стоит неразрешимая задача. Вместо этого в данном конкретном случае вам нужно спланировать задачи, которые выполняются после порогового времени, и быть готовыми к их отмене. Это неверно, вы можете использовать дисциплину и наложить ограничения на свой код для написания программ, которые доказуемо останавливаются. Единственное, о чем вам говорит проблема остановки, - это то, что не существует общего универсального метода определения того, останавливается ли случайная программа. - person ThePiercingPrince; 25.03.2015
comment
@ThePiercingPrince, перечитайте то, что я написал, исходя из практического примера. Человек, работающий с QA, не может написать оракул для произвольного кода. Значит, вы со мной согласны. - person Bob Cross; 25.03.2015
comment
перед вами неразрешимая задача. Это неверно. Если программа игнорирует ввод пользователя и останавливается, вы легко можете доказать, что она останавливается. Проблема остановки означает, что существует класс программ, для которых невозможно доказать. Большинство повседневных программ не относятся к этому классу. - person endolith; 24.04.2017
comment
@endolith, вы пытаетесь переопределить проблему остановки на что-то другое. Это не так. Это не относится к большинству повседневных программ. Проблема остановки описывает проблему, с которой вы столкнулись при рассмотрении набора всех возможных программ. - person Bob Cross; 26.04.2017
comment
Незначительный, очень педантичный момент - любой произвол - это что-то вроде тавтологии - любая программа или произвольная программа, с ударением / курсивом на любом или произвольном, описывает это - для меня ключевым словом было любое! Оба верны, но любая программа описывает это, возможно, более знакомым мне способом теории множеств. просто лингвистика, я думаю ... - person drkvogel; 13.10.2020
comment
@drkvogel, хотя я согласен с тем, что любое произвольное значение является избыточным, не сделает ли удаление любого из этих слов более ясным объяснение для тех, кто подходит к проблеме с позиции замешательства? Или в этом случае оправдана избыточность, просто как акцент на правиле, что нет, вы не можете руководить юристом или выбрать какой-то особый случай и объявить проблему остановки недействительной? - person Bob Cross; 13.10.2020
comment
@BobCross Я думаю, это просто вопрос того, насколько лингвистически правильным (или, возможно, педантичным!) Человек хочет быть - смысл в любом случае ясен, особенно если прочитать все объяснение. - person drkvogel; 14.10.2020
comment
Возможно, любой, произвольный, с акцентом на оба слова, разделенные запятой, охватывает все основы - оба термина подчеркнуты как ключевые к обсуждаемому вопросу, но запятая подчеркивает, что термины эквивалентны (по крайней мере, в этом контексте)? - person drkvogel; 14.10.2020

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

person dsimcha    schedule 10.07.2009
comment
Существует функциональный язык под названием Idris, в котором есть понятие complete функций, выполнение которых доказано за конечный промежуток времени при любом вводе, соответствующем определению типа для функции. Компилятор сообщит, если ваша функция complete. - person dansalmo; 29.11.2018
comment
Это самый емкий способ ответить на вопрос! Престижность! - person drkvogel; 13.10.2020

Вот простое объяснение доказательства неразрешимости проблемы остановки.

Предположим, у вас есть программа H, которая вычисляет, останавливается ли программа. H принимает два параметра: первый - это описание программы, P, а второй - вход, I. H возвращает истину, если P останавливается на входе I, и ложь в противном случае.

Теперь напишите программу p2, которая принимает в качестве входных данных описание другой программы p3. p2 вызывает H (p3, p3), затем зацикливается, если H возвращает истину, и останавливается в противном случае.

Что происходит, когда мы запускаем p2 (p2)?

Он должен зацикливаться и останавливаться одновременно, вызывая взрыв Вселенной.

person Graphics Noob    schedule 10.07.2009
comment
может кто-нибудь объяснить. H (p3, p3) и p2 (p2). - person OnePunchMan; 29.08.2016
comment
когда h принимает p2, p2, он сделает вывод, что намерение p2 является рекурсивным, поскольку оно, очевидно, продолжает делегировать работу повторяющимся шаблонам, и скажет, что оно не завершится, нет необходимости запускать программу, вы просто используете языковое исчисление и делаете выводы о том, как взаимодействуют последовательности преобразований среды. единственными неразрешимыми программами кажутся программы с неразрешимыми алгебрами, такими как целые числа, числа с двойной точностью, если такие условные выражения равны O (n) или выше, они неразрешимы, поскольку мы не можем показать, что они завершаются, не запустив их. - person Dmitry; 12.03.2017
comment
Да, это хороший ответ, но, пожалуйста, поясните несколько случаев. - person roottraveller; 14.07.2017
comment
Как доказать, что такая программа p3 существует? Если такой программы p3 не существует, p2 никогда не останавливается. - person fferri; 21.08.2017

Это настолько забито до смерти, что на самом деле существует поэтическое доказательство < / a>, написано в стиле Льюиса Кэрролла доктора Сьюза Джеффри Пуллумом (он из Language Log fame).

Забавные штуки. Вот вкус:

Вот трюк, который я воспользуюсь - и его легко сделать.
Я определю процедуру, которую я назову Q,
которая будет использовать предсказания P об остановке успеха
чтобы вызвать ужасный логический беспорядок.

...

Независимо от того, как P может работать, Q его вычерпает:
Q использует вывод P, чтобы заставить P выглядеть глупо.
Что бы P ни сказал, он не может предсказать Q:
P правильный, когда он неправильный, и ложный когда это правда!

person Doug McClean    schedule 10.07.2009

В Википедии есть подтверждение Проблема остановки.

Чтобы проиллюстрировать, почему простого применения некоторой техники к циклам недостаточно, рассмотрим следующую программу (псевдокод):

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;
  }
}

Можете ли вы придумать подход, который вернет истину, если этот код остановится, и ложь в противном случае?

Подумайте внимательно.

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

person Kevin Montrose    schedule 10.07.2009
comment
Это, конечно, само по себе не является доказательством. Конечно, маловероятно, что есть решатель проблем, который также знает ответы на все открытые проблемы математики. (Это также невозможно из-за неполноты.) Но простое обращение к его чрезвычайной сложности не является доказательством его невозможности. Я, безусловно, допускаю, что это хороший способ получить интуитивное представление о проблеме, и что в сочетании с неполнотой можно найти доказательства на этом пути. Доказательство диагонализации, приведенное в Википедии, OTOH, является правильным. - person Doug McClean; 13.07.2009
comment
Я мог бы скопировать доказательство из Википедии в свой ответ или процитировать его, а затем использовать пример, чтобы проиллюстрировать, почему интуитивные решения проблемы остановки неверны; используя примерно одинаковое пространство в любом случае. Я выбрал последнее, так как считаю его более полезным, чем формальное доказательство в контексте этого вопроса. - person Kevin Montrose; 13.07.2009
comment
Я с этим не возражаю. Я просто выбрасываю его туда, чтобы никто не запутался. Я подумал, что это хороший ответ. - person Doug McClean; 13.07.2009

«Если вы просто добавите один цикл, у вас будет программа остановки и, следовательно, вы не сможете автоматизировать задачу»

Похоже, кто-то слишком обобщает применение проблемы остановки. Существует множество конкретных циклов, которые можно завершить. Существуют исследования, которые могут выполнять проверку завершения для широких классов программ. Например, в Coq вы ограничены программами, прекращение которых вы можете подтвердить. У Microsoft есть исследовательский проект под названием Терминатор, в котором используются различные приближения, чтобы доказать, что программы будут завершены.

Но помните, проблема остановки заключается не только в игрушечных примерах. Ни один из них не решает общую «проблему остановки», потому что они не работают для каждой программы.

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

Пример программы, которая может или не может остановиться (в Haskell):

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;

Если каждое целое число> = 1, остановится ли эта программа? Что ж, до сих пор это работало, но нет теоремы, согласно которой он будет останавливаться для каждого целого числа. У нас есть гипотеза, связанная с Лотаром Коллатцем, которая датируется 1937 годом. это верно, но нет доказательств.

person Edward KMETT    schedule 10.07.2009
comment
+1 хотя бы за упоминание очень богатой области проверки программ. Конечно, проблема остановки в общем случае неразрешима, но существует большой класс программ, которые можно остановить. - person ShreevatsaR; 10.07.2009
comment
См. Понятие полных функций на функциональном языке Idris как пример того, как это встроено в компилятор. - person dansalmo; 29.11.2018

Отличный пример Тьюринга был самореферентным - предположим, есть программа, которая может исследовать другую и определять, остановится она или нет. Подайте САМ программу проверки останавливающейся программы в программу проверки останавливающейся программы - что она должна делать?

person n8wrl    schedule 10.07.2009
comment
Это ничего не доказывает: программа-контролер останавливающейся программы может просто сказать «Да», она останавливается, и нет никакого противоречия. Аргумент ориентирован на себя, но он более тонкий, чем то, что вы говорите. - person ShreevatsaR; 10.07.2009

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

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

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

Я держу пари, что, когда люди говорят «добавьте один цикл», они пытаются выразить идею о том, что, когда программа достаточно сложна, для нее требуется машина Тьюринга, и, следовательно, применима проблема остановки (как идея).

Это может немного не относиться к вопросу, но я считаю, что, учитывая эту деталь в вопросе, на это стоит обратить внимание. :)

person agorenst    schedule 12.07.2009
comment
Это зависит от того, можно ли показать программу как примитивно-рекурсивную. С помощью функциональной программы PR (или ее эквивалента в каком-либо другом стиле программирования) можно показать, что каждый цикл завершается, потому что вы можете найти показатель того, сколько работы ему осталось выполнить, который монотонно уменьшается. Но помимо PR существуют общие рекурсивные функции, о существовании которых не известно, и проблема остановки показывает, почему не существует алгоритма для поиска таких показателей. - person Donal Fellows; 08.10.2010

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

Предположим, у вас есть волшебная программа / метод определения остановки программы.

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;
}

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

Независимо от того, сколько проверок ввода вы выполняете, невозможно определить, останавливается ли КАЖДАЯ написанная программа или нет.

person ahawker    schedule 10.07.2009
comment
Вы забыли противоречие. Запустите свой Main на самом себе: если он определит, что он остановится, он будет работать вечно. Но если он определит, что он будет работать вечно, он остановится. Следовательно, определение невозможно, и DeterminesHalt не может существовать. - person Cypher2100; 12.07.2009
comment
Я согласен с @ Cypher2100. Проверьте ответ Graphics Noob выше, который демонстрирует полное доказательство. - person Vicky Chijwani; 18.11.2012

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

Похоже, в некотором роде, в Интернете есть очень интересное эссе: Who Can Назовите большее число?, которое касается машин Тьюринга и функций Аккермана.

person Don Wakefield    schedule 10.07.2009

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

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

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

person Ambuoroko    schedule 10.07.2009
comment
О, Боже. Вам нужно подумать о том, во сколько возможных состояний может попасть компьютер с 4 ГБ ОЗУ! - person Daniel Earwicker; 10.07.2009
comment
Вы можете рассматривать компьютеры как DFA, и тогда да, проблема с остановкой разрешима. Однако я бы ни в коем случае не называл это практичным. Если вы рассматриваете жесткий диск как часть конечного автомата, у вас есть больше состояний, чем вы когда-либо могли надеяться перечислить. - person Kevin Montrose; 10.07.2009
comment
Конечно ... это все еще практически не решаемо. Но теоретически решаемо. А кому не нравится небольшая бесполезная теория? - person Ambuoroko; 10.07.2009
comment
Нет, это не совсем решимость теоретически, в том-то и дело! И зачем вводить в него жесткие диски? Выясните, в скольких состояниях может находиться C-64. Кстати, во всей Вселенной всего 10-80 атомов. - person Daniel Earwicker; 10.07.2009
comment
Моя точка зрения была в основном своего рода забавным фактом, но я также намеревался проиллюстрировать некоторые различия между теорией и реальностью. Когда вы ДОКАЗЫВАете, что проблема остановки неразрешима, вы фактически доказываете ее для машины Тьюринга. Проблема остановки может быть решена на реальном компьютере. Если бы у вас была машина Тьюринга, запускающая вторичную программу на имитируемом компьютере, машина Тьюринга гарантированно остановилась бы и, таким образом, решила бы проблему остановки (на имитируемом компьютере) - person Ambuoroko; 10.07.2009
comment
Амбуороко: Память, необходимая для работы этого теоретического, но реального (?) Средства решения проблем, требует больше материи, чем есть во Вселенной. Я думаю, первое требование, чтобы доказать, что проблема остановки разрешима в реальном мире, - это найти гораздо больше материи. : P И хорошо, что мы построили этот зависающий компьютер, решающий проблемы! Мы все решили, да? Ой, подожди ... а как насчет этого компьютера ?! О нет!!!!!!! и Т. Д. - person agorenst; 26.08.2009
comment
Первым требованием для решения проблемы остановки в реальном мире может быть поиск дополнительных материалов ... но мы уже рассмотрели часть доказательства. В любом случае, все, что вам нужно, это настоящая машина Тьюринга, чтобы решить проблему для компьютера, и тогда мы уже знаем, что проблема неразрешима на машине Тьюринга. :-П - person Ambuoroko; 26.08.2009
comment
Машина Тьюринга определяется как имеющая конечное число состояний - person Tony; 26.12.2013

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

person Firas Assaad    schedule 12.07.2009

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

Предположим, у нас есть процессор с такими инструкциями, как mov, add, jmp, но без входа и выхода. И у нас есть память. В отличие от других процессоров, у этого есть другой регистр, называемый 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.

person zhengyitian    schedule 07.01.2018
comment
я начал задаваться вопросом, был ли мой ответ правильным. в Linux предположим, что файл elf не использует ввод / вывод, без потоковой передачи, без подпроцесса ... но может читать / записывать файл, и у него есть ограниченная память, дисковое пространство неограничено. там программа может решить, что такая вещь останавливается или нет? Программа может быть неограниченно большой, может принимать файл конфигурации, но имеет ограниченную память. Я перестаю думать об этом, потому что я боюсь, что отращу больше седых волос, делая это. - person zhengyitian; 07.12.2020

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

А теперь подумайте обо всех остальных случаях.

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

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

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

person Tom Hubbard    schedule 10.07.2009

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

person Adrian Panasiuk    schedule 10.07.2009

Из Programming Pearls Джона Бентли

4.6 Проблемы

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

while x != 1 do
    if even(x)
        x = x/2
    else
        x = 3*x +1
person Nick Dandoulakis    schedule 10.07.2009
comment
для получения дополнительных сведений об этой проблеме см., например: cecm.sfu.ca/organics/papers / lagarias Дело в том, что это еще не доказано. Кстати: спасибо, что заставили меня найти проблему, хе-хе, мне просто нужно было знать. - person Emile Vrijdags; 11.07.2009
comment
это похоже на небольшую легкую проблему. Но сюрприз! Это открытая проблема математики :-D Я писал в основном для развлечения и в качестве вызова;) - person Nick Dandoulakis; 11.07.2009

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

person Artyom    schedule 10.07.2009

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

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

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

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

person James Thompson    schedule 10.07.2009
comment
Если вы действительно решили это, я думаю, вы могли бы сделать лучше, чем rentacoder.com. :) - person John Smith; 10.07.2009
comment
Нам всем нужно с чего-то начинать! - person James Thompson; 10.07.2009
comment
И проект назывался Super Debugger. Хех. Ссылка на публикацию: - person Kevin L.; 04.08.2009

Еще один пример. Я недавно столкнулся с так называемыми числами града. Эти числа образуют последовательность с этими правилами

f(n) is odd  -  f(n+1) = 3*f(n)+1
f(n) is even -  f(n+1) = f(n)/2

В настоящее время предполагается, что все начальные точки в конечном итоге достигнут 1, а затем повторяются 4,2,1,4,2,1,4,2,1.... Однако для этого нет никаких доказательств. Итак, прямо сейчас единственный способ определить, заканчивается ли число при вводе в последовательность градин, - это фактически вычислить его, пока вы не дойдете до 1.

Это ключ к тому, как я понимаю проблему остановки. Насколько я понимаю, вы не можете наверняка знать, что программа остановится / не остановится, пока вы не действительно запустите ее. Таким образом, любая программа, которую вы пишете, которая может дать вам ответ наверняка на проблему остановки, должна будет фактически запустить программу.

person Mike Cooper    schedule 10.07.2009

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

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

person Todd Owen    schedule 26.08.2009

Вот моя попытка, отнеситесь к ней с недоверием.

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

Назовем такую ​​программу decider

Теперь предположим эти две программы:

program_1 (input){
    loop forever
}

и

program_2 (input){
    halt
}

Что касается program_1, мы можем легко сказать, что он никогда не остановится ни при каком вводе. Точно так же мы могли бы сказать, что program_2 всегда будет останавливаться при любом вводе.

Мы могли сказать это, просто посмотрев на их исходный код и не выполняя программы.

Может ли decider всегда искать исходный код и анализировать управляющие структуры, чтобы определить, остановится ли программа при вводе?

Чтобы ответить на этот вопрос, возьмите следующую программу:

program_3 (input) {
    
    ...func definition...

    result = func(input)

    if result = 12345

    then loop forever

    else halt
}

Предположим, что func - это функция, которая отображает целое число в целое число. А также предположим, что у func нет закрытой формы. Например, func может быть функцией, возвращающей входное простое число в последовательности простых чисел.

Теперь у нашего decider будут проблемы. Чтобы проанализировать исходный код program_3, он должен сказать, что func(input) будет отображаться. Таким образом, он должен каким-то образом включать все сопоставления, определенные func. Но существует бесконечное количество целых чисел и, следовательно, бесконечное количество таких отображений. Таким образом, включение всех деталей сопоставления в decider невозможно, что дополнительно означает, что decider не может анализировать исходный код и структуру управления program_3.

Это отвечает на наш вопрос. Нет decider не всегда может посмотреть исходный код и сказать, как программа будет себя вести. Может быть для некоторых программ, но не для всех.

Так как же вы думаете, что decider может что-то сказать о program_3. Он должен выполнить / смоделировать программу на входе, чтобы увидеть, что возвращает func.

Но предположим, что func имеет следующее определение:

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
}

Теперь func может бесконечно зацикливаться на некоторых входных данных, вызывая постоянный зацикливание program_3. Это означает, что, поскольку decider должен выполнять / моделировать program_3, он тоже может зацикливаться вечно, если program_3 зацикливается навсегда.

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

person rsonx    schedule 14.06.2021
comment
Решение об остановке не о том, существует ли вход, чтобы программа остановилась / не остановилась. Лицо, принимающее решение, только должно быть в состоянии определить, остановится ли конкретная программа с определенным вводом. Даже эта более простая задача невозможна, хотя и не с теми простыми функциями, которые вы упомянули. - person aschepler; 15.06.2021
comment
Мое внимание было сосредоточено на том, что остановившийся процесс принятия решения не всегда может просто взглянуть на исходный код и каким-то образом сказать, как программа будет себя вести. Вопрос, который задал OP, имеет отношение к тому, что мы не можем посмотреть источник и сказать, что произойдет. Другие люди уже ответили, в чем проблема с остановкой. Я просто хотел изложить свою точку зрения. Я надеюсь, что мое понимание правильное. Если нет, то не стесняйтесь исправлять любую ошибку. - person rsonx; 15.06.2021

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

Теперь дайте самому вашему алгоритму проверить.

person John Smith    schedule 10.07.2009

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

person Daniel Earwicker    schedule 10.07.2009

Изучите эту программу:

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;

Это остановится? Может ли компилятор предсказать, остановится ли он?

[Обратите внимание, что этот пример не доказывает невозможность проблемы остановки]

person Yves Daoust    schedule 15.06.2021

Решение: H обнаруживает H внутри H + и игнорирует вывод H + и принимает вывод самого себя H. Таким образом, проблема саморекламы решается путем обнаружения самореференции, таким образом, проблема остановки сводится к проблеме сокращения самодетектирования lol :)

В этом есть смысл, цикл - это форма саморекламы, которая ссылается на свою собственную отправную точку.

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

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

Возможно, такая машина может даже стать самосознательной, возможно, есть ссылка на самосознание :)

person Skybuck Flying    schedule 13.06.2021
comment
Добро пожаловать в Stack Overflow. Прочтите Как ответить. В частности, ответы должны быть попыткой ответить на вопрос. - person Chris; 15.06.2021
comment
Хорошо попробовали, но ваш аргумент не оправдывает ожиданий. Определение эквивалентности двух программ также является невыполнимой задачей, поэтому вы не можете выполнить самопознание. - person Yves Daoust; 15.06.2021