Множество Мандельброта
Одна формула — $z_{n+1} = z_n^2 + c$ — и из неё рождается, возможно, самая сложная фигура в математике.
Множество Мандельброта — набор таких комплексных чисел $c$, для которых последовательность $z_0 = 0,\; z_{n+1} = z_n^2 + c$ остаётся ограниченной.
В 1980 году Бенуа Мандельброт построил на компьютере картинку, которая поразила мир: чёрная «фигурка жука» с бесконечно изрезанной, ветвящейся границей. Поразительно, что эта неисчерпаемая сложность спрятана в одной из простейших формул, какие только можно записать.
Правило итерации
Берём комплексное число $c$ и запускаем процесс:
$$z_0 = 0, \qquad z_{n+1} = z_n^2 + c.$$
Если значения $z_n$ остаются ограниченными (не убегают в бесконечность), то $c$ принадлежит множеству. Если же $|z_n|$ начинает неудержимо расти, то $c$ — снаружи. Можно доказать: как только $|z_n| \gt 2$, последовательность гарантированно убегает. Это даёт простой численный критерий: итерируем, и если за разумное число шагов модуль превысил 2 — точка снаружи; если нет — считаем её внутри.
Печатаем карту в ASCII
Комплексное число $c = a + bi$ — это просто пара $(a, b)$. Перебрав сетку точек, нарисуем множество символами:
def escape_iters(cx, cy, max_iter=50):
zx = zy = 0.0
for i in range(max_iter):
zx, zy = zx * zx - zy * zy + cx, 2 * zx * zy + cy
if zx * zx + zy * zy > 4.0: # |z| > 2
return i
return max_iter
W, H = 60, 24
for row in range(H):
line = ""
for col in range(W):
cx = -2.3 + 3.2 * col / (W - 1)
cy = -1.2 + 2.4 * row / (H - 1)
it = escape_iters(cx, cy)
line += "#" if it == 50 else ("." if it > 5 else " ")
if line.strip():
print(line.rstrip())
Вывод:
.
....
.......
...####..
........###...#....
...#.###########.###.
...################...
............##################...
...#..#....#####################..
....########.#####################.
.. .....#.#############################.
.. .....#.#############################.
....########.#####################.
...#..#....#####################..
............##################...
...################...
...#.###########.###.
........###...#....
...####..
.......
....
.
Как работает под капотом
Символ # — это точки, не убежавшие за 50 шагов (предположительно внутри множества), а . — «пограничная зона», убежавшая, но не сразу. Обратите внимание на симметрию относительно горизонтальной оси: она следует из того, что сопряжённое число $\bar c$ ведёт себя зеркально. Раскрытие комплексного умножения $z^2 = (x+yi)^2 = (x^2 - y^2) + 2xy\, i$ объясняет две строки в коде: новая действительная часть — $x^2 - y^2 + a$, новая мнимая — $2xy + b$. Чем мельче сетка и больше итераций, тем тоньше прорисовывается «волосатая» граница — и она бесконечно сложна.
Частые ошибки
Самая частая — сравнивать $|z|$ с 2 через корень: дороже и не нужно, достаточно сравнить $x^2+y^2$ с 4. Вторая — стартовать с $z_0 = c$ вместо $z_0 = 0$ (получится похожая, но другая картинка). Третья — путать множество Мандельброта (перебираем $c$, всегда $z_0=0$) с множествами Жюлиа (фиксируем $c$, перебираем стартовое $z_0$).
Итог
- Множество Мандельброта: $c$ такие, что $z_{n+1}=z_n^2+c$ ограничена при $z_0=0$.
- Критерий убегания: как только $|z| \gt 2$, точка снаружи.
- Комплексный квадрат: $(x+yi)^2 = (x^2-y^2) + 2xy\,i$.
- Граница бесконечно сложна, фигура симметрична относительно оси абсцисс.