Айсберг больших чисел. Часть 4. Бездна
В трёх предыдущих частях мы рассмотрели просто большие числа, очень большие числа, и дошли до чисел, слишком больших даже для математики. Прочитайте сначала их, иначе этот пост не поймете!
Сегодня мы рассмотрим понятие вычислимости функций, расскажем про математических оракулов-экстрасенсов и затронем чуть-чуть философию.
Для понимания вам нужно обладать воображением и немного абстрактным мышлением, ну и знать математику на уровне 7-8 класса школы. Еще желательно знание основ программирования на любом языке.
Как всегда, пару источников по сегодняшней теме.
Сегодня будут пару теорем с пруфами, которые я буду отдельно помечать. Кто никогда не разбирался в математических доказательствах — можете их пропускать. Тем не менее, настоятельно рекомендую все же их просматривать, чтобы не было вопросов "а почему?" и "в смысле?".
Готовы? Поехали.
Начнем с парадокса интересного числа, который формулируется так:
Теорема: Докажем, что все числа интересны.
Доказательство: Пусть существуют неинтересные числа. Возьмем самое маленькое неинтересное число. Такое число — единственное в своем роде. Но разве это не делает его интересным?
Отсюда противоречие, значит, неинтересных чисел не существует.
Парадокс этот скорее шутливый, но у него есть и более серьезный аналог (парадокс Берри):
Теорема: Все натуральные числа можно описать, используя менее 10 слов.
Доказательство: Пусть существуют числа, которые нельзя никак описать менее, чем за десять словам. Выберем из всех этих чисел минимальное. Теперь опишем его, как "Наименьшее число, которое нельзя описать, используя менее 10 слов". В этом описании содержится 9 слов. Отсюда противоречие, а значит все числа можно описать менее, чем за 10 слов.
В чем же подвох?
(Сможет ли Уроборос сожрать себя целиком?)
Все эти парадоксы эксплуатируют один и тот же прием — самореференцию, или ссылку на самого себя. В простейшем виде самореференция выглядит так:
"Это предложение ложно". Если оно ложно, значит в нем говорится истина, но если оно истинно, значит оно ложно. Но ведь мы уже сказали, что оно не может быть ложным, потому что в этом случае оно было бы истинным, но в этом случае оно ложно, но...
В математике самореференция, если она приводит к парадоксу, означает, что что-то не так с предпосылками. В примере с "интересными" числами такой предпосылкой было утверждение, что принадлежность числа к "неинтересным" или "интересным" сама по себе может быть интересна. Второй пример чуть сложнее, но и там тоже все это есть — нельзя при описании числа использовать ссылку на само это описание числа. Получается порочный круг, деление на ноль, Марти Макфлай встретился сам с собой, а оба близнеца оказались старше друг друга.
Мы используем этот тип парадоксов, чтобы доказать существование невычислимых функций, то есть таких, для которых не существует хоть какого-то общего способа или алгоритма, их вычисляющего.
Вообще вычислить можно почти что угодно. Все те монстры от мира функций, о которых мы говорили в предыдущей статье (быстрорастущая иерархия) вычислимы, ведь их можно посчитать на каком-то вычислительном устройстве. Конечно, на обычном компьютере или тем более в уме сделать это невозможно. Важна лишь потенциальная возможность, лишь бы в вашем компьютере была неограниченная память и в вашем распоряжении имелось неограниченное время. (Заметьте, не бесконечность в прямом смысле, здесь и сейчас, а именно неограниченность!)
Чтобы наконец рассмотреть понятие вычислимости, надо как-то его формально определить. Для этого Алан Тьюринг придумал абстрактную машину, названную потом его именем — машину Тьюринга.
(картинка из интернета для наглядности)
Машина Тьюринга состоит из трех элементов — неограниченной в обе стороны ленты, разделенной на ячейки, считывающего устройства (головки), и набора правил, по которым машина, собственно, и работает.
В ячейках ленты изначально находятся какие-то символы (входные данные), а головка может находиться в одном из нескольких состояний. Правила описывают, что делать машине в случае, если головка находится в таком-то состоянии и находится напротив ячейки с таким-то символом. А может эта машина за один раз:
Записать в ячейку напротив головки некий символ (другой или такой же)
Сдвинуть головку на одну ячейку вправо или влево
Поменять состояние головки (на какое-то другое или оставить его тем же)
Остановить машину.
Вот пример правил для машины с двумя состояниями головки и двумя возможными символами в ячейке ленты:
Если головка находится в состоянии А, а в ячейке записан символ "0", записать в неё "1", сместить головку вправо и поменять её состояние на B.
Если головка находится в состоянии А, а в ячейке записан символ "1", сместить головку влево и оставить состояние А.
Если головка находится в состоянии B, а в ячейке записан символ "0", сместить головку влево и оставить состояние B.
Если головка находится в состоянии B, а в ячейке записан символ "1", записать в неё "0", сместить головку вправо и остановить машину.
Поиграться можно, например, здесь.
Сейчас мы не будем углубляться в эту тему, скажу лишь, что что на машине Тьюринга можно эмулировать любой алгоритм, который можно написать и на обычном языке программирования. Берите любой: Python, Java, C++ — эта грубая и уродливая машина Тьюринга справится с чем угодно. И вообще, в дальнейшем мы будем использовать термин "программа", а не "машина Тьюринга". (Но не забывайтесь, машины Тьюринга нам еще понадобятся).
Но есть одна задача, для которой силы машины Тьюринга не хватает — так называемая "проблема остановки". Решить проблему остановки — означает написать программу, которая узнает, остановится ли когда-нибудь данная конкретная программа или нет. (Чувствуете запах самореференции?)
Вроде бы очевидно, что проблема остановки разрешима: нужно лишь проверить, зацикливается ли программа в каком-то месте. Ну а если в правилах для этой машины вообще нет правила для её остановки, то очевидно, что она не остановится.
Но всё не так просто и вот пример. Возьмите какую-нибудь нерешенную до сих пор гипотезу для натуральных чисел, например, проблему Гольдбаха. (Её математики уже почти 300 лет решают!). Запустите программу, которая для каждого натурального числа проверяет, выполняется ли условие задачи. Если для очередного числа условие не выполняется, остановите программу. Математики за 300 лет не узнали, есть ли такое число, и у вас вряд ли выйдет.
На самом деле не существует такого алгоритма S, которому на вход подавалась бы запись любого другого алгоритма A, а на выходе он бы отвечал, останавливается ли A или нет.
Доказательство:
Пусть существует программа S, на вход которой подается запись любой программы A и входных данных к A, а на выходе она решает проблему остановки для программы A при этих входных данных: например — печатает одно из двух: "Программа останавливается" или "Программа не останавливается".
Напишем программу D, которая принимает на вход запись любой программы A и входных данных к A, выполняет внутри себя программу S, и, если S печатает "Программа останавливается", то D не останавливается (зацикливается), а если S печатает "Программа не останавливается", то D останавливается.
Подадим теперь на вход программы S запись программы D и любого входа к ней A. Если D останавливается, то S должна вывести, что D не останавливается, но если D не останавливается, то S должна вывести, что D останавливается, но если D останавливается, то S долж...
Мы получили парадокс, а значит, какое-то из наших предположений неверно. Если программа S существует, то программу D сделать очень просто. Значит, ошибочное предположение было в том, что существует программа S, которая решает проблему остановки.
Следовательно, проблема остановки неразрешима.
А причем здесь большие числа?
(ща все будет, не боись)
Возьмем все машины Тьюринга с произвольными правилами, числом состояний головки N и числом возможных символов M. Запустим их все на ленте, заполненной каким-то одним символом, и "посмотрим", какие из этих машин останавливаются, а какие нет. Из тех, что останавливаются, возьмем ту, которая останавливается за наибольшее число шагов. Обзовем эту машину Busy Beaver (рус. занятой бобр). (Аналогию с занятыми бобрами я считаю еще более запутывающей, поэтому объяснять ее не буду). Определим функцию BB(N, M), которая возвращает, собственно, число шагов до остановки машины Busy Beaver при числе состояний N и числе символов M. Эта функция, очевидно, невычислима, так как, чтобы ее вычислить, нужно решить проблему остановки. Более того, эта функция растет быстрее любой вычислимой функции!
Доказательство:
Пусть существует вычислимая функция f(N, M), которая растет так же или быстрее, чем BB(N, M). Но функцию f(N, M) можно записать в виде программы, а значит, и в виде машины Тьюринга для числа N_0 состояний и M_0 символов.
Возьмем теперь машину Тьюринга с N_1 > N_0 состояниями и M_1 > M_0 символами. Если эта машина не остановилась за f(N_1, M_1) шагов, то она уже не остановится, ведь мы предположили, что f(N_1, M_1) — это оценка сверху числа BB(N_1, M_1).
Но это значит, что, вычислив функцию f(N_1, M_1), мы, по сути, решим проблему остановки для любой машины Тьюринга с N_1 состояниями и M_1 символами. Следовательно, функция f(N, M) невычислима, и BB(N, M) растет быстрее любой вычислимой функции.
Вообще, что собственно этот ваш BB означает? Если говорить популярно и упрощенно, то BB(N, M) означает самое большое число, которое можно рассчитать с помощью программы, код которой "весит" не больше определенного количества байт. Помните парадокс Берри, с которого мы начинали — это тоже самое, только мы избавились от парадокса.
Как ни странно, BB(N, M) можно вычислить для небольших чисел, когда действительно можно понять, зацикливается программа или нет.
Часто используют другую функцию S(N) = BB(N, 2) — то есть используют машины Тьюринга с двумя символами на ленте, скажем "0" и "1". По состоянию на 2022 год известно, что
S(1) = 1
S(2) = 6
S(3) = 21
S(4) = 107. Что-то пока ничего необычного...
S(5) больше или равно 47 176 870. Некоторые машины с пятью состояниями демонстрируют слишком сложное поведение для человеческого понимания, поэтому оценка неточная.
S(6) больше или равно вот этому монстру:
, что больше, чем 10↑↑15 (вспомните нотацию Кнута).
Про S(7) нам неизвестно ничего, кроме того, что оно больше S(6).
Умельцы сконструировали машину Тьюринга с 19 состояниями и 2 символами, которая останавливается больше, чем за число Грэма шагов. Скорее всего, S(19) гораздо больше числа Грэма.
Другие мастера доказали, что S(748) невозможно вычислить в системе аксиом Цермело-Френкеля. Скорее всего, настоящая граница гораздо меньше 748.
Вообще (это уже мое предположение), числами S(N) можно измерять "силу" математических теорий: чем "сильнее" теория, тем для большего N можно вычислить S(N). Чтобы вычислить любое S(N), нужна, как мне кажется, бесконечно сложная теория бесконечной силы.
Число Райо из той же оперы, только использует не "язык" машин Тьюринга, а язык теории множеств, и определяется, как "наибольшее число, представимое на языке теории множеств с использованием гугола символов или меньше, плюс 1".
Математики, естественно, не стали останавливаться на этом.
Предположим существование оракула — мистической машины с неизвестным устройством, которая может решать проблему остановки обычной машины Тьюринга. Противоречий здесь никаких нет, потому что оракула нельзя "спросить" с помощью обычной машины. Если же мы позволим некой машине "высшего порядка" обращаться к нему, этот оракул больше не сможет решить проблему остановки по тем же причинам, что и в случае с обычной машиной. Чтобы решить проблему остановки снова, предположим существование "высшего оракула" или "оракула второго порядка". Но и он не сможет решить проблему остановки для машин, которые к нему обращаются. Так же мы можем предположить существование оракулов энного порядка, ну и в конце концов "абсолютного оракула", который может решить проблему остановки для любого оракула конечного порядка. Но и он сам не сможет решить проблему остановки для машин, которые его вызывают. На самом деле можно образовать целую иерархию оракулов, очень похожую на иерархию быстрорастущих функций.
Для машин, использующих оракулы, мы можем определить своих Busy Beavers и свои функции BB_k(N, M), где k — порядок оракула. Каждая следующая функция BB_k(N, M) растет быстрее любой "сверхвычислимой" функции предыдущих порядков.
С помощью похожих конструкций математик Джонатан Бауэрс наконец определил самое большое именованное конечное число в гугологии — Utter Oblivion (рус. Высшее Забвение). Ничего конкретного оно не означает, просто Бауэрс хотел, чтобы его число было самым большим.
Существует ли оракул на самом деле — проблема скорее философская. Есть несколько вариантов для существования оракула в нашем физическом мире, и, как по мне, вряд ли хоть какой-то из них возможен:
"Машина Зенона" — может выполнить бесконечное количество шагов за конечное время.
"Действительный компьютер" — может вычислить иррациональное число с бесконечной точностью.
Квантовый "сверхкомпьютер" с бесконечномерными кубитами (если я правильно понял).
Есть и другие умозрительные конструкции, про них лучше почитайте на Википедии.
Пожалуй, с конечными числами можно на этом закончить, несмотря на то, что даже самое большое из них — ничто по сравнению с бесконечностью. Но о них в следующий раз.