Когда я учился в средней школе, то часто вместо того, чтобы заниматься делом, рисовал всякую всячину. Тогда же я умудрился изящно изрисовать чертёжный лист, комбинируя и повторяя множество квадратов — получилось что-то среднее между Крутой S и треугольниками Пенроуза. Я чувствовал, что в этом рисунке кроется нечто большее, но тогда мне ещё не хватало знаний для полноценного осмысления его принципов. В итоге, решив делегировать эту задачу будущему себе, который гораздо лучше знает математику, я повесил своё творение на стену за письменным столом, где оно провисело на протяжении моей учёбы в старших классах и колледже и висит по сей день.

Однако время шло, и сегодня я уже стал той самой будущей версией себя, которая разбирается в математике чуть лучше. Ну а поскольку мой фрактал похож на распускающийся цветок и провисел на моей стене столько лет, я буду ласково называть его «желтофиоль», хотя ниже вы увидите, что он сильно похож на некоторые другие известные фракталы. Прежде чем переходить к изучению этого узора, будет нелишним проговорить этапы, которым мы следовали в школе при его рисовании:

  1. Начинаем с одного квадрата.

  2. Добавляем четыре копии этого квадрата слева, справа, сверху и снизу.

  3. Добавляем четыре копии текущего состояния с небольшим смещением (около 27° по часовой стрелке) слева, справа, сверху и снизу от него.

  4. Чередуем шаги 2 и 3, пока не кончится чертёжный лист.

Вот анимированная версия:

Выражаю признательность manim и 3Blue1Brown за то, что сделали эту и многие другие визуализации!
Выражаю признательность manim и 3Blue1Brown за то, что сделали эту и многие другие визуализации!

По аналогии с кривой Госпера перечисленные этапы можно повторять, покрывая любую часть плоскости, и использовать каждое промежуточное состояние в качестве элемента этой мозаики. Если у вас есть чертёжная бумага и достаточно свободного времени, попробуйте сами — очень интересно смещать фигуру, полученную на предыдущем шаге, и обводить её контур, наблюдая, как всё встаёт на свои места, подобно пазлу. Кстати, ещё где-то десять лет назад я понял, что можно генерировать контур с помощью L-системы. Механизм здесь простой и заключается в поворотах на 90° вправо (R) и влево (L):

  1. Начинаем с четырёх поворотов вправо: RRRR

  2. На каждой итерации используйте следующие замены: R → RLR, L → RLL

К примеру, после первой итерации замен у вас должно получиться RLRRLRRLRLR. Ниже показаны первые несколько шагов применения этого механизма:

Жёлтый означает, что следующий поворот (по часовой стрелке) будет влево, Синий — вправо.
Жёлтый означает, что следующий поворот (по часовой стрелке) будет влево, Синий — вправо.

А вот анимированная версия:

При использовании обоих этих методов мы получаем равнозначный результат… Хотя, стоп! Когда я впервые попробовал L-систему год назад, то подумал, что сгенерировал такой же контур, как у желтофиоля. Иными словами, я пытался от руки нарисовать четвёртую итерацию с её множеством правых поворотов и на полпути остановился с мыслью «раз сработало в первых трёх итерациях, значит, работает в целом, Ч. Т. Д.» И только когда я начал делать анимации для этой статьи, то понял, что два этих метода расходятся. Вот сравнение четвёртой итерации каждого:

Основное отличие в том, как «копии» третьей итерации разм��щаются вокруг исходного центра. Первый метод (будем называть его «перетаскиванием») ведёт к размещению копий непосредственно сверху, снизу и так далее от центра, а при использовании L-системы они размещаются по диагонали. Контур, создаваемый L-системой, уже описан в нескольких источниках:

В то же время вариант, полученный «перетаскиванием», в картинках Google и статьях Wikipedia я найти не могу. Интересно, почему один настолько популярнее второго? Немного поэкспериментировав, я нашёл правила для генерации своей настенной версии этого фрактала (L → RLR, R → LLR). Однако они вызывают странный эффект, на каждом шаге будто «разворачивая» направление, в котором ты рисуешь контур. К примеру, на первом шаге происходит переход от (RRRR) (множества поворотов вправо) к (LLRLLRLLRLLR) (большинству поворотов влево). Есть и ещё один логичный вопрос — если оригинальный механизм L-системы размещает копии не вдоль осей координат, то под каким углом он это делает? Оказывается, что эффект «разворачивания», углы поворота L-системы и кажущиеся произвольными 27° удивительным образом связаны. Но прежде, чем переходить к этому нюансу, нужно разобрать важный вопрос.

Нумерация

За десять с лишним лет прокрастинации по мере всё более углублённого изучения математики у меня было достаточно возможностей взглянуть на этот фрактал по-новому. В первый год института я узнал, как показать, что мощность натуральных чисел N равна мощности пар натуральных чисел N2, используя функцию Кантора для их упорядоченного переплетения на координатной плоскости. Я также узнал, что можно проецировать натуральные числа на спираль, демонстрируя, что N имеет ту же мощность, что и пара целых чисел Z2.

Иллюстрация функции Кантора взята из Wikipedia, а изображение спирали — из UCB CS70 
Иллюстрация функции Кантора взята из Wikipedia, а изображение спирали — из UCB CS70 

Обе эти техники напомнили мне то, как желтофиоль заполняет пространство в координатной плоскости, расширяясь наружу из своего центра. Чтобы использовать структуру желтофиоля в качестве функции сопряжения, нам потребуется найти способ нумеровать «очерёдность» размещения каждого квадрата, желательно так, чтобы это соответствовало его рекурсивному построению. Естественной стартовой точкой будет обозначение центра фрактала как 0. Начиная оттуда, мы по часовой стрелке пронумеруем четыре добавляемые в первой итерации квадрата как 1, 2, 3 и 4:

Теперь нужно подумать, как размечать квадраты в следующей итерации. Один из вариантов — нумеровать их в порядке появления, считывая сверху вниз и слева направо:

Вот только получается это не совсем фрактально — то есть порядок в этом случается, кажется, несвязанным с рекурсивной структурой фрактала. А что, если снова использовать подход нумерации «из центра», как при обозначении квадратов с 0 по 4? Всё же каждый «лепесток» является копией первой итерации, последовательность построения которой мы уже обозначили. Вот вариант использования схемы нумерации с 0 по 4 внутри каждого отдельного синего лепестка и между ними (пунктирные линии):

А вот расширение на следующий набор лепестков:

На первый взгляд кажется хаотичным, но если взглянуть на расположение конкретных чисел, мы заметим интересные особенности. Если рассматривать только числа, кратные 5, то получается масштабированная сетка, повёрнутая по часовой стрелке примерно на 27°:

А если взять только числа вида 5n + 1, мы получим ту же сетку, только сдвинутую вверх на один квадрат:

Если же взять только числа, кратные 25, получим другую сетку, с ещё более масштабированными ячейками:

Похоже, что число 5 имеет особую связь с фракталом. И причина становится очевидной, если взглянуть на количество квадратов в каждой итерации. В стартовой итерации квадрат один, в первой их 5, во второй — 25, в третьей — 125 и так далее. Поскольку каждая итерация строится путём добавления к предыдущему состоянию четырёх дополнительных копий, на каждом её шаге происходит 5-кратное масштабирование. С учётом этой особой связи с числами, кратными 5, и степенью 5, возникает желание переделать разметку с десятичной системы на пятеричную. Тогда получим следующее:

Очень много информации, но, если выделить только паттерн итерации 3 и его копию справа, то можно заметить кое-что интересное…

Расширение

Если взять любое число в лепестке слева и отсчитать от него пять шагов вправо, то мы найдём его копию в бирюзовом лепестке. При сравнении чисел в таких клетках выясняется, что значение клеток-копий всегда представляет исходное значение +200. Например, в пяти шагах от 44 вы найдёте 244, а в пяти шагах от 3 — 203. В каком-то смысле добавление 200 как бы кодирует «смещение» на пять шагов вправо. Причём это свойство «смещения» работает и в других формах: рассмотрите, к примеру, расположение 0, 1, 2, 3 и 4 относительно 30, 31, 32, 33 и 34.

Если разглядывать фрактал достаточно долго, вы заметите, что любое число можно разложить на разряды, скажем, 231 на 200 + 30 + 1, и по его частям определить, где оно находится на сетке. Конкретно в этом случае мы находим на сетке векторы, соответствующие 200, 30 и 1, и для определения позиции 231 складываем их:

Вы можете сами протестировать числа таким же образом, раскладывая их на разряды и добавляя векторы. Если предположить, что этот подход работает в общем, то для уточнения расположения любого числа на сетке достаточно узнать, где находится каждое составное число его разложенной формы, и связать эти точки. Теперь мы внесём нотацию, определив vec(n) как вектор, указывающий, где на сетке располагается число n. Используем в качестве примера наши одноциферные значения:

Используя эту нотацию, мы можем пронаблюдать, как ведут себя «степени 10»:

При внимательном рассмотрении можно заметить паттерн:

Именно в виде этой условной формулы я изначально написал код визуализации. Но мне стало интересно, а есть ли более элегантный способ вычислить значения без использования условий? В идеале нам нужно преобразование, которое можно будет повторно применять для масштабирования и поворота вектора на основе значения n, то есть матрица, возводимая в степень n. В результате некоторых экспериментов я нашёл матрицу М и её степени:

И она удобно соответствует ожидаемым значениям, не требуя включения в уравнение условий:

Аналогичным образом можно настроить уравнения для других возможных цифр:

Если вглядеться в эту проклятую нотацию сквозь слёзы, то можно заметить связь с системами счисления, а именно пятеричной и десятичной. Аналогично тому, как в десятичной системе число 1234 разложилось бы на:

В пятеричной оно раскладывается на:

Теперь для кодирования позиций во фрактале мы используем матрицу M в качестве основания, а векторы в качестве цифр:

В итоге мы получили систему счисления не на основе скаляров, а на основе матрицы и векторов. При подсчёте от нуля можно понять, как эта система согласуется со структурой фрактала:

Определители

Вы могли заметить, что 20 и 40 поменялись местами в сравнении с исходной нумерацией. Дело в том, что мы выбрали в качестве М отрицательный определитель det(M) = -5, что ведёт к побочному эффекту в виде «разворачивания» пространства при каждой итерации. Теперь, когда мы знаем, что наш фрактал имеет связь с линейной алгеброй, можно визуализировать эту связь в стиле 3Blue1Brown, наложив масштабированные сетки, которые показывают, как степени М влияют на наши «цифры-векторы» 1⃗ , 2⃗ , 3⃗ и 4⃗ .

Чтобы избежать такого переворачивания, нужно выбрать матрицу с положительным определителем. Например:

Визуализация при использовании новой матрицы:

В этом варианте вместо «разворачивания» и повторного выравнивания по осям с каждой итерацией происходит вращение векторов по часовой стрелке. Стоп, а разве мы не видели подобную версию фрактала в самом начале, когда говорили об L-системе? Действительно, использование в качестве основы M′ ведёт к воспроизведению версии, полученной с помощью L-системы:

Загадка разгадана! Два итоговых фрактала почти одинаковы, но тот, что висит у меня на стене, сгенерирован с использованием для матрицы определителя det(M) = −5, а более типичный — с использованием det(M′) = 5. Выбор матрицы также проливает свет на то, откуда берутся, казалось бы, случайные ~27°. Возможно, вы обратили внимание, что абсолютное значение обоих определителей равно 5, и оно удобно совпадает с тем, что фрактал при каждой итерации увеличивается в пять раз. Если выбрать для матрицы больший определитель, векторы будут расти слишком быстро и на каждом шаге оставлять за собой «пустое пространство». Например, использование определителя -6 приведёт к такому узору:

Если же выбрать меньший определитель, векторы будут расти слишком медленно, и выстраиваемые в ходе каждой последующей итерации узоры начнут накладываться. Вот вариант при определителе -4:

Значит, нам нужно, чтобы матрица имела определитель ±5. Кроме того, в ней должны использоваться целочисленные элементы, чтобы она всегда отображала векторы в целочисленные координаты. И так уж совпало, что вектор ⟨1,2⟩ содержит целочисленные элементы и имеет величину √5, то есть мы можем выполнить описанные требования, использовав его сам и его повёрнутую на 90° форму в качестве столбцов матрицы. Вычисление угла этого вектора даёт \arctan 2/1 \approx 63.43^\circ, то есть наклон «примерно 27°» в сторону от оси y.

Расширение, продолжение

Вы могли заметить, что сложение векторов в большинстве случаев даёт неверный результат, то есть 2⃗ + 2⃗  ≠ 4⃗. Исключением являются случаи, в которых используется разложенная форма числа. И это ожидаемое поведение, поскольку 2 и 4 выбирались для того, чтобы отразить связь с пятеричной системой счисления, но с фактическим направлением векторов они не связаны. Возможно, будет лучше обозначить нумерацию от 1 до 4 как вверх (1⃗ ), вправо (2⃗ ), вниз (3⃗ ) и влево (4⃗ ). Естественно, противоположные направления друг друга отменяют, то есть 1⃗ + 3⃗ = 2⃗ + 4⃗ = 0⃗. Но что насчёт других комбинаций сложений? Давайте внимательно взглянем на нумерацию в пятеричной системе и обратим внимание, куда указывают комбинации единичных векторов:

Это позволит создать таблицу на основе того, каким получится результат сложения этих векторов:

 Таблица симметрична по диагонали, то есть сложение является коммутативным, что в случае векторов не удивительно. Самое же важное, что несколько операций приводят к двухзначным числам. Вроде бы ничего особенного, но это означает, что при сложении более крупных чисел придётся задуматься о переносе остатка в следующую цифру. К примеру, если мы захотим найти число непосредственно над 22, то можем выполнить сложение 22⃗ + 1⃗. При использовании традиционного сложения столбиком и переноса получится:

Если вас это смущает, напомню, что 2⃗ + 1⃗ = 13⃗. И если вас удивляет, что такое вычисление вообще работает, то вы не одиноки. Поскольку я просто пишу статью, а не доказательство, то проверку адекватности этой схемы сложения оставлю вам.

Антракт. Сопутствующие темы

Идея использования элементов, выходящих за рамки N в системе натуральных чисел, уже была известна, благодаря сбалансированному тернарному представлению, в котором в качестве цифр используются -1, 0 и 1, а в качестве основания — 3. Если такое представление расположить вдоль одного измерения по оси x, то мой желтофиоль можно выразить как его 2D-аналог, добавив две новых цифры, отражающие положительное и отрицательное направления оси y. Существует и альтернативная схема для обобщённых сбалансированных тернарных представлений, которая охватывает любое число измерений, используя пермутоэдры (насколько я смог в этом разобраться). В двух измерениях мы в итоге получаем гексагональную решётку:

Визуализация обобщённого сбалансированного тернарного пред��тавления в 2D с использованием гексагонов (источник: Wikipedia). Также читайте про Gosper Curve, которая подобна гексагональному желтофиолю.
Визуализация обобщённого сбалансированного тернарного представления в 2D с использованием гексагонов (источник: Wikipedia). Также читайте про Gosper Curve, которая подобна гексагональному желтофиолю.

Ещё одна экзотическая система счисления — это Quater-imaginary Base (четвертичная мнимая система), в которой в качестве основания используется мнимое значение 2i, а в качестве цифр — 0, 1, 2 и 3. Если представить сложные числа как векторы, а 2i как матрицу, отвечающую за масштабирование и вращение, то можно преобразовать эту систему счисления в нашу проклятую нотацию:

В качестве альтернативы можно преобразовать матрицу с положительным определителем (M′) в её эквивалент из комплексных чисел, чтобы получить систему с основанием 2 + i. Идея сбалансированной системы с основанием 2 + i (вместе с построением изящных фракталов) подробно рассматривается в работе Тимоти Джеймса Маккензи Макариоса. Я наткнулся на неё, когда искал визуализации четвертичной мнимой системы в картинках Google, и понял, что эта связь была установлена ещё в 2016 году. Немного смущает тот факт, что я нашёл эту информацию после того, как сделал анимацию в начале. Получается, что автор работы уже меня опередил, хоть и использовал версию фрактала на основе M′, а не M (насколько я знаю, M нельзя закодировать в виде комплексного числа).

Когда я понял, что система счисления с матричным основанием действительно работает, то начал искать, не провёл ли кто ещё подобную связь между фракталами, замощением, линейной алгеброй и системами счисления.

Что удалось выяснить:

  • Проект «BinSys» под руководством Аттилы Ковача занят поиском матричных оснований конкретно с определителем 2. Его цель — создать обобщённую форму двоичной системы.

  • В работе «Replicating Tesselations» Эндрю Винс проделывает все необходимые математические вычисления, формализуя то, что я упорно пытаюсь объяснить своими мутными рассуждениями. Причём его трактовка распространяется на любую решётку, а не только Z2.

    • В ней также можно найти доказательства альтернативного способа обобщения сбалансированной тернарной системы на более высокие измерения.

Кстати, о мутных рассуждениях. Следующий раздел уже полностью построен из того, о чём я начал размышлять, когда приступил к написанию статьи, так что никакой однозначности, которая могла бы возникнуть за годы обдумывания задачи, здесь нет. Вместо этого, я опираюсь на ментальную модель линейной алгебры в стиле: «Если нечто звучит как правда и похоже на правду, значит, это наверняка правда».

Особенности переноса желтофиоля в 3D

В средних классах я сильно увлекался Minecraft, поэтому мне всегда было интересно — а будет ли механизм фрактала работать для кубов? Говоря точнее, есть ли способ создать 3D-версию моего фрактала, начав с куба и пошагово копируя фигуры группами по шесть, формируя «трёхмерный плюс»? В основном эта идея сводится к тому, какие свойства требуется получить при обобщении на матрицу 3х3. Мне на ум пришли такие:

  • Все записи в матрице должны быть целыми числами. Это необходимо, чтобы после применения к векторам матричного основания (6 единичным векторам по осям), они по-прежнему содержали целочисленные значения в каждом компоненте. В работе Винса это описывается как «эндоморфизм Λ», то есть отображение решётки Λ = Z3 на саму себя.

  • Каждый вектор-столбец матрицы должен быть удалён от начала координат на 3 шага по метрике Хэмминга. Это требование обеспечит, чтобы 6 копий трёхмерного плюса, создаваемые во второй итерации, не накладывались на оригинал, центрированный в начале координат, но при этом были смежными с ним.

  • Нужна матрица с определителем ±7. Поскольку с каждой итерацией фрактала добавляется шесть новых копий, на каждом шаге его размер увеличивается в 7 раз. Если мы хотим правильно «упаковать» эти копии вместе, нужно сделать так, чтобы применяемая матрица масштабировала входные значения также в 7 раз.

Применив поиск перебором к триплетам векторов с расстоянием Хэмминга равным 3, мы получим чёткую матрицу 3х3, отвечающую всем этим требованиям:

А вот её визуализация:

Мда, выглядит ужасно! Первым в глаза бросается то, что в более поздних итерациях узор как бы «съезжает», в результате чего оголяются фрагменты предыдущих итераций. К примеру, во второй итерации видно, что можно заделать эти оголённые участки, добавив ещё два трёхмерных плюса с центрами в координатах ⟨1,1,1⟩ и ⟨−1,−1,−1⟩.

Здесь мы добавили два дополнительных плюса, обозначенных жёлтым, и визуализировали центральные точки всех 8 плюсов. Вот только возникает ощущение, что такая «заплатка» работает слишком хорошо. Если взглянуть на центральные точки 8 новых плюсов, то видно, что они расположены как вершины искривлённого куба. Я всё ещё не уверен, что это может значить. Похоже, такое расположение связано с тем фактом, что кубы (8 вершин, 6 граней) являются двойственными к октаэдрам (6 вершин, 8 граней). Возникает очевидное желание взять этот новый куб и сделать из него 6 копий, но я не хочу сильно отклоняться от темы, так что отложим это на другой раз.

При визуальном рассмотрении кажется, что проблема второй итерации в несимметричном расположении плюсов вокруг центра, в результате чего фрактал расширяется неоднородно. Найти более симметричное расположение плюсов вручную сложно — в некотором роде это напоминает теорему о причёсывании ежа. Достаточным (и, возможно, необходимым) условием для предотвращения этого «съезжания» фрактала будет выбор матрицы, в которой все столбцы попарно ортогональны друг другу и имеют одинаковую величину. Подозреваю, что совместить это требование с предыдущими в контексте трёх измерений не выйдет. Длина каждого целочисленного столбца-вектора должна быть равна ∛7. Значит, если x, y и z — это целые числа, то нужно решить следующее уравнение:

Но оно никогда не будет верно, так как левая сторона всегда целочисленная, а правая — иррациональная. К счастью, если подняться до четвёртого измерения, то математика сработает нам на руку. В 4-х измерениях компоненты каждого вектора должны удовлетворять следующему уравнению:

Которое сработает, если 3 из 4 компонент вектора принять равными ±1, а последнюю установить как 0. Оказывается, в гиперпространстве очень много места, что даёт массу возможных матриц с подобными столбцами, которые удовлетворят всем предыдущим условиям. Вот матрица, обладающая ещё одним свойством, о котором мы поговорим ближе к концу:

Теперь, когда у нас есть подходящая матрица, можно визуализировать наш 4-х мерный фрактал. Один из вариантов для этого — сделать 3D-срезы 4D-пространства, зафиксировав значение w:

Базовый случай получается скучным даже при четырёх измерениях. Вот первая итерация:

Начиная с этого момента, вы сможете лучше понять, как визуализация работает. Фиолетовые кубы слева и справа, которые вроде как находятся в основании, фактически расположены в следующих координатах (0,0,0,−1) и (0,0,0,1) соответственно.

Здесь видно, что элементы итерации 1 продолжают просвечивать в итерации 2, что вызывает беспокойство, поскольку именно таков был симптом съезжания фрактала в 3D версии. Однако при более внимательном рассмотрении это поведение пока не такое пугающее. Если всерьёз вникнуть в концепцию 4-х измерений, то можно увидеть, что хоть два плюса в w = 0 и не выглядят сбалансированными, слева (w = -1) и справа (w = 1) расположено по три плюса, которые можно рассмотреть как ортогональные относительно плюсов в w = 0. Тройки кубов, расположенные по обеим сторонам (w =± 2), являются частью 4D-плюсов, которые выпячивают в третьем измерении в срезах по краям.

Для меня основной вывод таков, что вторая итерация ещё немного видна, но первая уже полностью скрыта. В техническом смысле третья итерация ещё дальше протягивается в измерение w, но здесь осмыслить фрактал становится уже слишком сложно. Представляю, что именно такую картину 4-х мерный я повесил бы на 4D-плоскость в своей 5D-комнате, чтобы восхищаться всем её величием. Так что назову её соответственно — «ортофлореус». К сожалению, моё жилище измеряется в квадратных метрах, а не гиперкубических, поэтому сложно оценить этот узор в полной мере. К тому же, у визуализации 4D объекта с помощью 3D срезов есть пара проблем:

  • Проекция слишком быстро уходит в горизонтальном направлении, занимая драгоценное пространство экрана (или стены). Особенно заметно, что в третьей итерации для визуализации всего узора приходится добавлять два дополнительных среза.

  • Моё ограниченное 3-х мерное зрение не способно видеть внутренности 3D-объектов (как я могу видеть внутренности закрашенных 2D квадратов на бумаге), что не даёт по достоинству оценить всю структуру.

Но оба этих ограничения можно обойти. Для этого нужно использовать вложенную сетку 7x7 из сеток 7x7, которая позволит визуализировать структуру в стиле первой анимации статьи:

Для тех, кто желает восхититься этим фракталом, вот статичное изображение последней итерации. Если это не прекрасно, то что тогда?
Для тех, кто желает восхититься этим фракталом, вот статичное изображение последней итерации. Если это не прекрасно, то что тогда?

В каждой вложенной сетке отражается срез от -3 до 3 по осям x и y, а в общей сетке сеток представлены срезы от -3 до 3 вдоль осей z и w. Всякий раз, когда квадрат переходит из одной малой сетки в другую, по факту он перемещается по оси z или w. Квадраты, которые исчезают или появляются, на деле входят или выходят из «окна просмотра» 7х7х7х7 в 4-х измерениях. В сравнении с линией из 3D-срезов этот подход более эффективно задействует доступную площадь (фрактал растёт в виде квадрата, а не линии) и позволяет увидеть внутреннюю часть всей структуры, не закрытую предыдущими итерациями. Кроме того, такой дизайн отлично сочетается с уже висящим на моей стене фракталом.

Если убрать всю помпезность анимации и просто присвоить каждой клетке фрактала по одному пикселю, то мы сможем увеличить окно просмотра вплоть до размера 31х31х31х31:

Весьма сложная картина, но она хотя бы подтверждает, что фрактал последовательно расширяется вовне без излишнего смазывания, которое наблюдалось в 3D. И лично я думаю, что это прекрасный узор для какого-нибудь стёганого одеяла или коврика для пикника. Особенно красиво смотрятся вот эти срезы рядом с самым центром:

И тут возникает логичный вопрос: «А можно ли продолжить расширение на более высокие измерения?» К сожалению, нет. Если применить все наши прежние требования, то потребуется измерение d, которое удовлетворит условию:

В левой стороне отражена величина, которую должен иметь каждый вектор, чтобы матрица с d взаимно ортогональных столбцов имела определитель 2d + 1, обеспечивая достаточное масштабирование входных объектов для размещения добавляемых в каждой итерации 2D-копий. Правая же сторона — это набор возможных величин целочисленных векторов, удалённых от начала координат на расстояние 3 по Хэммингу, чтобы созданные во второй итерации копии касались фигуры первой итерации, но не накладывались на неё. Если проанализировать с помощью графиков, то получится, что единственными измерениями, при которых это условие можно выполнить, будут 1 (сбалансированная тернарная система счисления), 2 (желтофиоль/квадратичная снежинка) и 4 (ортофлореус).

Ну и, как я уже писал, для нашей 4-х мерной системы счисления мы выбирали в качестве основания особую матрицу. В частности, такую, которая кодирует кватернион i + j + k, то есть теперь по аналогии с четвертичной мнимой системой у нас есть способ кодировать кватернионы в «сбалансированное девятеричное кватернионное представление». В этой схеме девятью возможными цифрами являются 0, ±1, ±i, ±j и ±k с основанием i + j + k. А поскольку я плохо знаком с кватернионами и до сих пор не уверен, что эта теория работает, то делегирую эту задачу будущему себе, который разбирается в математике лучше. В последний раз эта стратегия сработала весьма неплохо.

Заключительные мысли

Когда-то у меня была мечта об обществе без дефицита, в котором проблема заключается в отсутствии у людей мотивации делать что-либо, так как все их потребности удовлетворены. Решением этой проблемы было то, что раз в несколько лет все люди старше определённого возраста должны сообщать о чём-то прекрасном, что они разузнали о мире. В противном случае их бы превращали в сойлент или что-то подобное (да, без дефицита ≠ утопия). Как бы то ни было, мне нравится думать, что открытие странного цветка с пилообразными лепестками, бесконечно расцветающими вдоль 4-х мерного пространства, уберегло бы меня от переработки на какое-то время.

И я, наконец, вернулся к этой идее в попытке освежить страсть к математике и программированию после периода выгорания. В итоге оказалось, что молодой я оставил прекрасный подарок в виде квеста, пролегающего по разным сферам, включая фракталы, системы счисления, линейную алгебру и высокие измерения. Интересно, сколько ещё ярких идей у других людей отложено рядом в виде каких-то зарисовок или списков задач.

Если эта статья показалась вам сбивчивой из-за множества переключений между разными областями, то всё потому, что я пытался воссоздать тот путь, которому хаотично следовал долгие годы, то берясь за эту задачу, то бросая её. В ней есть места, где вы могли задаться вопросом: «Как ты понял, что конкретно это решение приведёт вот к этому результату?» Всё просто — никаких подсказок у меня не было. Я лишь интуитивно пробовал разные подходы, и эта статья подчёркивает те части, которые сработали. Надеюсь, что через написание и визуализацию своей цепочки рассуждений мне удалось доступным языком выразить все связи для тех исследователей фракталов, кто осмелится нырнуть в эту кроличью нору.

И напоследок ещё один поворот. Внимательный читатель наверняка заметил, что ни одна из приведённых по тексту визуализаций не соответствует фракталу на моей стене, который показан в самом начале статьи. Четвёртая итерация (светло-зелёная) размещена с ошибкой примерно в 27°:

И тут забавный случай из разряда «почему я помню это, но не помню, что ел на обед два дня назад». Я в точности запомнил свой ход мысли в тот момент более десяти лет назад. Я думал, что фрактал перестанет совпадать с основными направлениями, если его постоянно наклонять в одну и ту же сторону относительно осей. Как мы видели выше в случае с M и M′, моё интуитивное желание компенсировать наклон было разумным, разве что корректировка уже сама собой происходила в ходе чередующихся этапов. Поначалу меня сей факт слегка смутил, но потом я вспомнил, что даже Дональд Кнут допустил неверный поворот при проектировании фрактала для размещения у себя на стене. Ошибаться, ошибаться и снова ошибаться, но всё реже, реже и реже!