"Информатика (базовый и углублённый уровни) (в 2 частях)", Поляков К.Ю., Еремин Е.А.
Не для каждой задачи можно создать программу, которая всегда за конечное время выдаёт правильный ответ. Такие задачи называют алгоритмически неразрешимыми: ограничение здесь не в недостаточной скорости компьютера, а в невозможности общего решателя. Главный пример — проблема остановки: вопрос о том, завершится ли произвольная программа на заданных данных. Понимание этой темы помогает увидеть принципиальные границы вычислений и строго доказывать их с помощью противоречия и сведения задач.
Текст подготовлен нейронной сетью по теме параграфа и не заменяет учебник — важные факты и формулировки сверяйте с ним.
Алгоритмически разрешимая задача — задача, для которой существует алгоритм, завершающий работу на любом допустимом входе и дающий правильный ответ. Иными словами, алгоритм не может бесконечно перебирать варианты или ошибаться на части данных. Это определение нужно, чтобы отличать настоящий решатель от программы, которая справляется лишь с некоторыми примерами.
Алгоритмически неразрешимая задача — задача, для которой не существует алгоритма, правильно решающего её на всех допустимых входах. Речь идёт именно об отсутствии общего способа, а не о нехватке мощности конкретного компьютера. Понятие помогает установить принципиальную границу того, что можно автоматизировать.
Проблема остановки — задача о том, завершится ли произвольная программа на заданных исходных данных. Проверяющему алгоритму нужно было бы ответить «да» или «нет» для любой пары «программа — вход». Это центральный пример, на котором показывают существование неразрешимых задач.
Сведение задач — преобразование входов одной задачи во входы другой, позволяющее перенести вывод о разрешимости или неразрешимости. Если бы ответ на преобразованный вход решал исходный вопрос, то решатель второй задачи мог бы служить решателем первой. Этот приём нужен, чтобы доказывать неразрешимость новых задач, опираясь на уже известную.
Трудная задача и неразрешимая задача отличаются не временем, которое уходит на вычисления, а наличием общего алгоритма. Для трудной задачи решатель существует, хотя он может работать очень долго, и при достаточном времени всё-таки завершится. В случае неразрешимой задачи нельзя построить алгоритм, который на каждом допустимом входе гарантированно остановится и ответит верно. Поэтому увеличение быстродействия компьютера не устраняет неразрешимость.
Проблема остановки относится к неразрешимым, потому что предполагаемый универсальный проверяющий алгоритм можно заставить оценивать не только произвольные программы, но и программу, построенную специально для проверки этого алгоритма. Если бы такая проверка всегда давала правильный прогноз, можно было бы использовать его в поведении специальной программы. Противоречие показывает, что исходное предположение о существовании универсальной проверки неверно.
Противоречие возникает так: пусть проверяющий алгоритм сообщает, остановится ли программа на заданном входе. Создадим программу, которая получает описание программы, обращается к проверяющему алгоритму и делает наоборот: если тот предсказывает остановку, программа зацикливается, а если предсказывает бесконечную работу — завершается. Теперь запустим эту программу на её собственном описании. Любой прогноз приводит к противоположному результату, значит, проверяющий алгоритм не может существовать.
Чтобы доказать неразрешимость другой задачи, используют сведение. Представим, что для новой задачи найден решатель, и преобразуем вход известной неразрешимой задачи так, чтобы ответ решателя сообщал ответ на исходный вопрос. Тогда решатель новой задачи позволил бы решить и известную задачу, что невозможно. Следовательно, предположение о решателе новой задачи было ошибочным. При сведении нужно обосновать, что преобразование действительно сохраняет связь между ответами.
Отсутствие общего алгоритма не запрещает анализировать отдельные случаи. Например, по короткой программе можно сразу увидеть, что она выводит число и завершается, или что её цикл бесконечен при заданных условиях. Для другой программы ответ может оказаться сложнее, но это не меняет общего результата о проблеме остановки. Неразрешимость утверждает, что единого решателя для всех возможных программ и входов не существует.
| Признак | Алгоритмически разрешимая задача | Алгоритмически неразрешимая задача |
|---|---|---|
| Существует ли общий алгоритм | Да, для всех допустимых входов. | Нет алгоритма для всех допустимых входов. |
| Требование к ответу алгоритма | Он завершается и отвечает правильно. | Общий алгоритм с таким свойством невозможен. |
| Что можно заключить о каждом отдельном входе | Решатель обработает каждый допустимый вход. | Отдельный вход иногда можно решить анализом. |
| Пример | Проверка, чётно ли заданное целое число. | Проблема остановки произвольной программы. |
Сначала сравните строки о существовании алгоритма и требованиях к его ответу: именно они задают строгое различие между классами задач. Строка об отдельных входах напоминает, что общий результат не предсказывает ответ для каждой конкретной программы. Примеры показывают один решаемый случай и центральную неразрешимую задачу.
Задача 1. Для программы с единственной командой «вывести 1» определить, завершится ли она на заданном входе. Здесь программа не содержит цикла или условия, которое могло бы изменить ход выполнения. Нужно рассмотреть именно данный текст программы, а не пытаться решить проблему остановки для всех возможных программ.
Ответ: программа завершится на любом допустимом входе. Вывод получен прямым анализом конкретной программы, а не универсальной проверкой остановки.
Задача 2. Определить, остановится ли программа, которая увеличивает счётчик, пока тот не достигнет заданного конечного числа. Предположим, что счётчик начинает с нуля, а конечное число — натуральное. Условие остановки достижимо, потому что при каждом повторении значение счётчика увеличивается на единицу и не уменьшается.
Ответ: при этих условиях программа завершится за конечное число шагов. Если начальное значение или условие цикла заданы иначе, их нужно отдельно учесть: вывод относится к указанному варианту.
Задача 3. Предположить, что существует алгоритм, который для любой программы и любого входа определяет, завершится ли выполнение, и показать противоречие. Обозначим предполагаемый проверяющий алгоритм через H: он получает описание программы и вход, затем сообщает прогноз «остановится» или «не остановится». Построим программу D, которая использует ответ H, чтобы поступить ему наперекор.
Ответ: такого универсального проверяющего алгоритма не существует, поэтому проблема остановки алгоритмически неразрешима. Противоречие возникло из-за предположения о безошибочном решателе.
Ошибка: считать неразрешимую задачу просто очень долгой. Так думают, потому что медленное выполнение похоже на отсутствие результата. Но для долгой разрешимой задачи алгоритм всё равно обязан завершиться, тогда как неразрешимой нельзя иметь решатель для всех входов. Проверьте себя вопросом: доказано ли отсутствие общего алгоритма или речь только о большом времени работы?
Ошибка: объявлять задачу неразрешимой, потому что не удалось найти алгоритм. Неудача поиска показывает лишь, что решение пока не найдено, а не что его не существует. Для вывода о неразрешимости требуется доказательство, например противоречие или корректное сведение. Проверьте себя: приведён ли аргумент, исключающий любой возможный общий решатель?
Ошибка: путать отсутствие общего алгоритма с невозможностью решить конкретный пример. Её допускают, перенося общее утверждение на каждый отдельный вход. Между тем простой случай может иметь очевидный ответ при прямом просмотре кода. Проверьте себя: утверждается ли невозможность решить именно этот пример или только невозможность универсального способа?
Ошибка: считать решателем программу, которая иногда не завершается или ошибается. Такая программа может быть полезной подсказкой, но она не удовлетворяет определению алгоритмической разрешимости. Решатель должен завершиться и дать правильный ответ на каждом допустимом входе. Проверьте себя, разобраны ли все случаи, включая те, где программа может зациклиться или получить необычные данные.
Для изучения темы нужны понятия алгоритма, программы, входных данных и завершения вычислений. Чтобы разобраться в доказательстве проблемы остановки, полезно уметь прослеживать выполнение программы и понимать условие цикла. Противоречие строится методом доказательства от противного: временное предположение приводит к невозможному результату. Наконец, понятие неразрешимости помогает оценивать принципиальные ограничения программ и вычислительных систем, а не только их скорость и объём памяти.
Чем неразрешимая задача отличается от задачи, которая долго решается?
Долгая задача имеет алгоритм решения, хотя ему может понадобиться очень много времени. Для неразрешимой задачи невозможно создать алгоритм, который правильно и за конечное время ответит на каждом допустимом входе.
Почему нельзя создать универсальную программу для проверки остановки?
Если предположить, что такая программа существует, можно построить другую программу, которая поступает противоположно её предсказанию о собственной остановке. В результате возникает противоречие, поэтому универсального решателя нет.
Можно ли узнать, остановится ли конкретная программа?
Часто можно: например, если программа выводит число и сразу завершает работу, ответ очевиден. Неразрешимость означает отсутствие общего алгоритма для всех программ и входов, а не невозможность анализировать отдельные случаи.
Что означает сведение одной задачи к другой?
Это преобразование входа первой задачи во вход второй, при котором ответ второй помогает получить ответ первой. Если таким способом известную неразрешимую задачу можно решать с помощью предполагаемого решателя другой задачи, то этот решатель привёл бы к невозможному результату.
Как доказать, что задача алгоритмически неразрешима?
Один из способов — доказать от противного: предположить, что решатель существует, и вывести логическое противоречие. Другой распространённый приём — сведение: показать, что решатель новой задачи позволил бы решить уже известную неразрешимую задачу.
§ 35. Алгоритмически неразрешимые задачи