Двумерное блуждание и закон √N
Выпустим блуждающую точку не на прямую, а на бесконечную клетчатую плоскость: на каждом шаге она идёт вверх, вниз, влево или вправо. Через сколько шагов она уйдёт от старта на сто клеток? Ответ прячет в себе один из самых красивых законов случайных процессов.
Закон корня из N — типичное расстояние, на которое случайное блуждание уходит от старта за N шагов, растёт пропорционально квадратному корню из N, а не самому N.
Этот закон объясняет, почему запах духов доходит до другого конца комнаты за минуты, а не за секунды, хотя молекулы движутся со скоростью сотен метров в секунду. Они не летят по прямой — они блуждают, сталкиваясь миллиарды раз в секунду, и потому продвигаются медленно. Понять закон корня из N — значит понять, почему диффузия так нетороплива и почему «вдвое дальше» стоит «вчетверо дольше».
Четыре направления вместо двух
В одном измерении было два варианта шага. На плоскости их четыре: (1, 0) — вправо, (-1, 0) — влево, (0, 1) — вверх, (0, -1) — вниз. Точка хранит две координаты x и y, и каждый шаг меняет ровно одну из них на единицу. Расстояние от старта считается по теореме Пифагора: корень из суммы квадратов координат, в Python это math.hypot(x, y).
Одна траектория нам ничего не скажет — она случайна. Поэтому мы запустим много блужданий одной длины и усредним финальные расстояния. Это и будет «типичное расстояние» для данного числа шагов.
Измеряем рост расстояния
import random, math, statistics
random.seed(8)
def walk_distance(steps):
x = y = 0
for _ in range(steps):
dx, dy = random.choice([(1, 0), (-1, 0), (0, 1), (0, -1)])
x += dx
y += dy
return math.hypot(x, y)
print(f"{'шагов':>7} {'ср.расстояние':>14} {'sqrt(n)':>9}")
for steps in (100, 400, 1600):
avg = statistics.mean(walk_distance(steps) for _ in range(2000))
print(f"{steps:>7} {avg:>14.2f} {math.sqrt(steps):>9.2f}")
Вывод:
шагов ср.расстояние sqrt(n)
100 8.87 10.00
400 17.71 20.00
1600 35.67 40.00
Каждую строку мы получаем, усредняя расстояние по 2000 независимых блужданий. Третий столбец — для сравнения — это просто sqrt(steps). Смотрите внимательно на числа: они и есть закон в действии.
Что говорят числа
Сравним строки. Когда число шагов растёт в четыре раза (со 100 до 400, затем с 400 до 1600), среднее расстояние удваивается: 8.87 → 17.71 → 35.67. Это ровно √4 = 2. Если бы расстояние росло линейно с числом шагов, оно бы вырастало в четыре раза, а не в два. Рост вдвое при учетверении шагов — подпись квадратного корня.
Заметьте и устойчивое соотношение между столбцами: среднее расстояние составляет примерно 0.886 от sqrt(n) (8.87/10, 17.71/20, 35.67/40 — все около 0.886). Это не случайность: для двумерного блуждания среднее расстояние теоретически равно (√π / 2)*√N ≈ 0.886*√N. Наша симуляция воспроизвела точную константу из теории — приятное подтверждение, что мы всё сделали верно.
| Шагов N | Во сколько больше шагов | Ср. расстояние | Во сколько больше расстояние |
| 100 | ×1 | 8.87 | ×1 |
| 400 | ×4 | 17.71 | ×2 |
| 1600 | ×16 | 35.67 | ×4 |
Главный практический вывод: чтобы уйти вдвое дальше, нужно вчетверо больше шагов (то есть вчетверо больше времени). Дистанция «дорожает» квадратично. Именно поэтому диффузия эффективна на малых масштабах (клетка получает питательные вещества за доли секунды) и безнадёжно медленна на больших (без перемешивания сахар растворялся бы в стакане часами).
Как работает под капотом
Откуда берётся корень? Ключ — в среднем квадрате расстояния. Можно показать, что E[x*x + y*y] растёт линейно с числом шагов: каждый независимый шаг добавляет в средний квадрат фиксированную порцию, а вклады перекрёстных слагаемых в среднем гасятся, потому что направления шагов независимы. Раз средний квадрат расстояния растёт как N, то само расстояние (корень из квадрата) растёт как √N. Корень появляется именно при переходе от «квадрата расстояния» к «расстоянию».
Теперь о коде. statistics.mean(walk_distance(steps) for _ in range(2000)) принимает генераторное выражение: функция mean вытягивает 2000 расстояний по одному и усредняет их, не создавая список целиком. В f-строках мы выравниваем колонки: {steps:>7} прижимает число вправо в поле шириной 7, а {avg:>14.2f} — вправо в поле 14 с двумя знаками после запятой. Символ > в спецификаторе формата означает выравнивание по правому краю; именно благодаря ему столбцы в выводе ровные.
Частые ошибки
- Ожидать, что расстояние растёт линейно с числом шагов. Оно растёт как корень: вчетверо больше шагов — лишь вдвое дальше.
- Мерить по одной траектории. Отдельное блуждание случайно; закон проявляется только при усреднении по многим запускам.
- Считать расстояние как
x + yвместоmath.hypot(x, y). Расстояние на плоскости — это гипотенуза, корень из суммы квадратов, а не сумма координат. - Забыть, что среднее смещение (вектор) по-прежнему ноль из-за симметрии — растёт именно среднее расстояние (длина вектора).
- Путать выравнивание в f-строке:
{x:>7}— вправо,{x:<7}— влево. Перепутав, получите кривые столбцы.
Итоги
- В двумерном блуждании четыре равновероятных направления; расстояние от старта — это
math.hypot(x, y). - Типичное расстояние от старта растёт как √N: вчетверо больше шагов дают лишь вдвое большее расстояние.
- Точная константа для плоскости — около 0.886*√N, и симуляция её воспроизводит.
- Корень возникает потому, что средний квадрат расстояния растёт линейно с числом шагов.
- Этот закон управляет скоростью диффузии: «вдвое дальше» стоит «вчетверо дольше».