Алгоритм решения «проблемы остановки» Тьюринга

23

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

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

Могу ли я найти язык программирования (или языки), где я для каждой программы на этом языке могу решить, будет ли программа завершена или работать вечно?

Кава
источник
Аналогичный вопрос: stackoverflow.com/questions/8412741/…
3
В мае у CACM была очень интересная статья: Доказательство завершения программы
Кристоф Уэлш
3
«общий алгоритм [...] для некоторых возможных пар программных входов» - это почти противоречит самому себе. Я предполагаю, что вы хотите ограничить себя бесконечным подклассом всех программ?
Рафаэль

Ответы:

25

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

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

Могу ли я найти язык программирования (или языки), где я для каждой программы на этом языке могу решить, будет ли программа завершена или работать вечно?

Нет, если этот язык полон по Тьюрингу, нет.

Однако существуют полные языки, отличные от Тьюринга, такие как, например, Coq , Agda или Microsoft Dafny, для которых проблема остановки решаема (и фактически определяется их соответствующими системами типов, что делает их полными языками (то есть программа, которая может не завершиться, не будет компиляции)).

sepp2k
источник
1
Класс примитивно-рекурсивных функций является хорошо известным «языком программирования», для которого проблема остановки тривиально разрешима.
Рафаэль
Существует несколько языков « полного функционального программирования », в которых все программы закономерно заканчиваются.
Андерсон Грин
3

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

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

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

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

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

Yttrill
источник
4
Я думаю, что это вы полностью и совершенно упустили из виду. Первый абзац вашего ответа не относится к вопросу, потому что он спрашивает об алгоритмах, а не о том, что человек может или не может доказать. Остальная часть ответа отвечает на первый абзац вопроса, то есть может ли алгоритм доказать завершение для некоторых программ. Каждый из предыдущих ответов уже сказал «да» этому.
2012 года
3
Ваше утверждение о том, что можно написать алгоритм, который может доказать завершение каждой хорошо написанной программы на достаточно простом на языке Тьюринга языке, полностью неверно. Для каждого возможного алгоритма, который пытается доказать завершение, существуют проблемы, когда каждая программа, которая решает эту проблему, не может быть доказана остановкой этим алгоритмом. Поэтому, если вы не говорите, что каждая программа, решающая эту проблему, написана плохо по определению (что было бы нелепо), это опровергает вашу точку зрения.
2012 года
1
@Sam Если кто-то спросит меня, останавливается ли какой-нибудь код, я посмотрю на код и попытаюсь выяснить. Но я не алгоритм. И да, можно написать алгоритм, который может проверить, останавливается ли программа для большого количества программ. Но это не то, что сказал Иттрилл. Иттрилл сказал, что это возможно для всех хорошо написанных программ. И, как я сказал в своем предыдущем комментарии, это просто ложь, если вы не утверждаете, что некоторые проблемы могут быть решены только плохо написанными программами (что опять-таки было бы смешно).
2012 г.
1
@ Сэм «мне кажется простым, что программы, намеренно написанные для остановки, легко анализируются на предмет условий остановки» - если бы это было так, почему у нас нет таких инструментов? Это не так, как будто люди не пытались. (Один из виновников - переопределение методов: во время компиляции вы не знаете весь код, который будет выполняться.)
Рафаэль
1
@ Сэм "есть ли бесконечный цикл" - сложная вещь, даже для реального цикла. Конечно, меня учили, как найти петлевые инварианты, но это не значит, что я могу найти их (легко) во многих случаях. Насколько я знаю, угадай и докажи это золотой стандарт в наши дни. Опять же , если были достаточно общие алгоритмы, я бы ожидать , что они будут включены в основные компилирует или Иды (которые делают выполнить некоторые тривиальные, синтаксические проверки). Можете ли вы дать ссылку на достаточно сильный алгоритм?
Рафаэль
3

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

однако в информатике нет точного термина для «программ», которые «иногда» оказываются успешными. Слово «алгоритм» обычно зарезервировано для программ, которые всегда останавливаются.

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

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

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

AXBYXYXYBA

в CS эта «иерархия квазиалгоритмов», кажется, до сих пор изучалась в основном неформально.

это проявляется в исследовании занятых бобров [1] и в проблеме PCP [2]. фактически компьютерная атака на PCP на основе ДНК может рассматриваться как квазиалгоритм. [3] и это замечено в других областях, уже отмеченных, таких как доказательство теорем [4].

[1] Новая атака тысячелетия на проблему занятого бобра

[2] Решение проблемы с сообщениями Zhao (v2?)

[3] Использование ДНК для решения проблемы ограниченной почтовой корреспонденции . Kari et al.

[4] доказательство завершения программы Cook et al., Comm. ACM

(так что это на самом деле очень глубокий вопрос, который defn заслуживает того, чтобы быть на TCS.SE imho ... может быть, кто-то может переспросить его таким образом, чтобы он подходил и оставался)

ВЗН
источник
В качестве впечатляющего примера того, насколько мощными могут быть квазиалгоритмы, ACM указывает, что функция Аккерманна может быть остановлена ​​квазиалгоритмом, но она больше (не вычисляется) всеми примитивными рекурсивными функциями.
vzn
1
«Слово« алгоритм »обычно зарезервировано для программ, которые всегда останавливаются». - Я не уверен, что это правда. Есть много частично завершающих алгоритмов (особенно в проверке), и я никогда не слышал, чтобы кто-нибудь говорил «алгоритм».
Рафаэль
Есть неформальное использование «алгоритма». "частично завершается" нормально, но, вероятно, не является стандартным. как уже говорилось, пока не существует стандартного термина. Википедия определяет алгоритм как эффективный метод, т. е. разрешимый со следующими характеристиками (1) всегда дает ответ, а не дает ответ; (2) всегда давать правильный ответ и никогда не давать неправильный ответ; (3) всегда завершаться за конечное число шагов, а не за бесконечное число; (4) работать для всех случаев проблем класса.
vzn
а затем позже в той же статье говорится: «Дальнейшее разъяснение термина« эффективный метод »может включать в себя требование о том, что при наличии проблемы извне класса, для которого метод эффективен, метод может останавливаться или зацикливаться навсегда без остановки , но не должен возвращать результат, как если бы он был решением проблемы ". то есть это почти противоречит самому себе!?! очевидно, что по ключевому вопросу существует некоторая путаница, и существующая терминология не является строгой. обратите внимание, что слово «алгоритм» близко к более чем тысячелетней давности и существенно изменилось…
vzn
Это правда: традиционное значение, вероятно, означает «эффективный метод» в том смысле, как это говорит Википедия (в предложении, которое вы цитируете, нет никакого противоречия, хотя это немного неясно) - люди не придумали функции / алгоритмы, которые не заканчивались (для некоторые входы). Я думаю, что это изменилось с 1950-х годов; как я уже сказал, сегодня люди явно называют частично завершающий метод «алгоритмом».
Рафаэль
2

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

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

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

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


источник
3
«Поскольку все языки, кроме самых примитивных, являются полными по Тьюрингу (требуется только что-то вроде переменных и условных выражений)» Это не так. Во-первых, вам, по крайней мере, понадобится рекурсия или какая-то циклическая конструкция (которая должна быть такой же мощной, как цикл while - простого цикла подсчета недостаточно). Во-вторых, я не думаю, что есть много людей, которые бы называли такие языки, как Coq или Agda (которые являются полными и, следовательно, не точными), примитивными или игрушечными языками.
sepp2k
@ sepp2k: ну да. Арифметика Пеано также весьма полезна и не завершена по Тьюрингу. Упрощенное утверждение, я полагаю. Если ОП достаточно знаком с проблемой, она, надеюсь, сможет заполнить технические детали.
3
Существует огромный разрыв между «достаточно сложным» и полным по Тьюрингу. Coq действительно сложен, и он подходит для очень широкого круга практических задач.
1
@Kerrek SB Хорошо, возможно, что полный по Тьюрингу язык используется способами, которые остаются доказуемыми до прекращения. Если вы можете доказать, что рекурсивная формула всегда приближается к своему завершающему условию (например, функция факториала), вы можете доказать, что она завершается, даже если вы не сможете обработать каждый тип рекурсии.
@ArtB: Конечно, всегда есть некоторые программы, которые могут быть завершены. Первый вопрос ОП может намекнуть на это, хотя я не уверен, что полностью им следую. Например, у вас не может быть «общего алгоритма», который определяет, завершается ли какое-либо конкретное семейство программ, и наоборот, вы, вероятно, могли бы создать ограниченное семейство функций, так что, предполагая, что функция принадлежит этому семейству, вы могли бы алгоритмически определить, является ли она завершается. (Я не уверен, что эта семья может быть нетривиальной, хотя. Я думаю, что может, но я не могу привести пример.)
2

TT

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

ALogTimecM

Кава
источник
1

Да, вы можете, но я сомневаюсь, что это будет полезно. Вам, вероятно, придется сделать это с помощью анализа случаев, и тогда вы сможете найти только наиболее очевидные случаи. Например, вы можете grep файл для кода while(true){}. Если файл имеет этот код, он никогда не завершится ^. В более общем смысле вы могли бы сказать, что программа без цикла или рекурсии всегда завершается, и есть несколько случаев, которые вы могли бы сделать, которые могли бы гарантировать, что программа будет или не прекратится, но даже для программы среднего размера это будет очень сложно и во многих случаях не сможет дать вам ответ.

tl; dr: Да, но вы не сможете использовать его для большинства полезных программ.


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


источник
4
Как вы думаете, почему Coq и Agda бесполезны? Вы переоцениваете ценность полноты по Тьюрингу.
Я использовал Coq, но мои претензии остаются, поскольку большинство коммерческих программ написано на Java / C ++ / Ruby / C #, для которых мои утверждения верны. Такие программы, которые 90% людей интересуются написанием, не принесут пользы. По сути, если вы не знаете Coq / Agda и т. Д., Вы не целевой рынок для него.
5
Я бы сказал, что 99% реальных программ выиграют от реализации в не полностью тьюринговом подмножестве языка. Например, вы не будете выполнять функцию Аккермана каждый день. 100% CRUD не нуждается в «реальном» языке. Обработка данных почти всегда тривиальна. Посмотрите проект Terminator - они даже обслуживают приличное подмножество возможных программ на C ++, чего более чем достаточно для реальных вещей (включая драйверы и другой низкоуровневый код).
Большинство реальных проектов хотят повторно использовать библиотеки, написанные на языках, полных тьюринга, и использовать их IDE, отладчики и учебные пособия. Да, вы могли бы делать что-то на языках, не являющихся тьюринговыми, но я не могу представить, чтобы кто-то действительно говорил «Я хочу сделать Х», а мой ответ «Использовать Coq». ps- спасибо за то, что познакомили меня с Проектом Терминатора .
4
невообразимо огромная часть бизнес-логики уже реализована в SQL, не полном Тьюринга. И DSL, и eDSL сейчас растут. Таким образом, вскоре большинство программистов бизнес-приложений забудут обо всех языках «общего назначения».