Случайность, которой нет.
компьютер не умеет быть случайным. каждое «случайное» число вычислено. seed определяет всё. это детерминизм, притворяющийся хаосом.
Каждый раз, когда программа вызывает random(), она не получает случайное число. Она вычисляет следующее число в строго детерминированной последовательности. Это называется псевдослучайный генератор, или PRNG. Pseudo — потому что не настоящий. Random — потому что выглядит случайным.
Простейший пример — линейный конгруэнтный генератор: xn+1 = (a · xn + c) mod m. Четыре числа: a, c, m — параметры алгоритма. x0 — seed, начальное значение. Всё. Это «случайность» в большинстве игр восьмидесятых и многих утилитах до сих пор1.
Seed определяет всю последовательность. Один seed — одна последовательность чисел. Всегда одна и та же. Это используют разработчики игр: один seed генерирует целый процедурный мир. Minecraft — каждый мир определён единственным числом. Один seed = один уникальный мир, со всеми пещерами, деревьями и деревнями ровно на тех местах. Но он детерминирован полностью. Тот же seed — тот же мир, до последнего блока, в любой день и на любом устройстве.
Никто, кто рассматривает арифметические методы, не может избежать состояния греха. — Джон фон Нейман
Это и есть идея null: абсолютно детерминистски и абсолютно стохастически одновременно. Sequence задана формулой и воспроизводима до последней цифры. И при этом, если смотреть на неё «снаружи», она выглядит случайной — статистические тесты не отличат её от настоящей случайности. Это та же двойственность, что и у π: число, в котором каждая цифра вычислима по формуле, и при этом в нём не находят отклонений от равномерного распределения.
Современные PRNG устроены сложнее линейного конгруэнтного. Mersenne Twister, разработанный Мацумото и Нисимурой в 1998 году, — алгоритм с периодом 219937 − 1. Последовательность повторится через 105984 чисел. Больше, чем атомов в наблюдаемой вселенной, возведённых во много степеней2. Для большинства задач — более чем достаточно. И всё равно полностью детерминировано.
Для криптографии обычный PRNG не годится. Если знаешь параметры и несколько последовательных выходных чисел — можно восстановить внутреннее состояние и предсказать все последующие. Криптографические PRNG (CSPRNG) устроены иначе: их выход вычислительно неотличим от случайного, и обратная задача — восстановление seed по выходу — требует нерешаемой за разумное время вычислительной работы. Но и они детерминированы в смысле «один seed — одна последовательность».
Откуда тогда берётся настоящая случайность? Из физики. Тепловой шум электроники. Время между нажатиями клавиш пользователя. Микродвижения мыши. Радиоактивный распад. Linux собирает это в /dev/random — пул энтропии из физических событий. Когда нужна по-настоящему непредсказуемая величина — например, для генерации криптографического ключа — система ждёт, пока в этом пуле накопится достаточно битов реальной физической случайности.
Но и здесь возникает вопрос: случаен ли сам радиоактивный распад? Квантовая механика говорит, что да — по крайней мере в копенгагенской интерпретации, в которой момент распада принципиально непредсказуем и не определён до момента наблюдения. В интерпретации со скрытыми переменными можно предположить, что есть какие-то параметры, которых мы не видим, но которые полностью определяют время распада. Джон Белл доказал в 1964 году, что локальные скрытые переменные невозможны — они дают предсказания, отличающиеся от квантовомеханических, и эксперименты раз за разом подтверждают именно квантовые3. Но нелокальные скрытые переменные остаются открытым вопросом. Возможно, случайности нет вообще нигде. Возможно, вселенная детерминирована полностью — и random() в этом смысле даже честнее, чем кажется: он лишь честно показывает, что вычислимость и непредсказуемость — это два разных понятия.
Для Sonic Pi seed — это художественное решение. `use_random_seed 31415` — и всё, что после этой строки, детерминировано, до последней ноты, до последней миллисекунды паузы. Один seed = одно произведение. Воспроизводимо бесконечно, на любом компьютере, в любой стране. Музыка, которая кажется живой и неожиданной — но записана одним числом и алгоритмом из десяти строк. Это не имитация случайности. Это именно то, чего я хочу: структура, которая выглядит как хаос, и оказывается порядком при ближайшем рассмотрении.