Как рисовать по клеточкам автоматы: Simple but Stunning: Animated Cellular Automata in Python

Просто, но потрясающе: анимированные клеточные автоматы в Python

Автоматизация олицетворяет последние несколько десятилетий быстрого технологического развития, когда многие процессы происходить без вмешательства человека. Но что именно это означает?

Автомат (существительное):

  • : относительно самодействующий механизм
  • : машина или механизм управления, предназначенный для выполнения заранее определенной последовательности операций

Это два наиболее распространенных определения слова автомат , связанных со словом автомат , автоматический или автоматический .

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

Один очень простой автомат показан на рисунке ниже:


Рис. 1: Простой автомат с двумя состояниями. Взято из Википедии.

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

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

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

клеточных автоматов .

Клеточный автомат опирается и мотивируется принципами живых организмов в природе. Он состоит из сетки ячеек, каждая из которых имеет некоторое состояние. Каждая клетка продвигается во времени в соответствии с некоторым математическая функция соседних ячеек. Таким образом, все автоматы ведут себя как живой организм.

К концу этого сообщения в блоге вы сможете понять и увидеть потенциал клеточных автоматов. Во-первых, мы углубимся в формальное определение и подробнее остановимся на некоторых частных случаях. Затем, чтобы завершить головоломки, мы увидим, как реализовать некоторые интересные клеточные автоматы в Python, дополненные интересные анимированные визуализации с использованием Matplotlib. Следите за обновлениями!

Определение клеточного автомата

Клеточный автомат полностью определяется тремя ключевыми элементами:

  1. Коллекция из «цветных» ячеек, каждая из которых имеет состояние;
  2. Ячейки распределены по сетке заданной формы и
  3. Ячейки обновляют свое состояние в соответствии с правилом, основанным на соседних ячейках.

Например, мы можем взять самый простой случай, когда состояние ячейки либо включено, либо выключено, или, другими словами, либо 1, либо 0.

Сетка в целом представлена ​​​​в виде прямоугольника с формой \( M \times N \), что означает, что она имеет М строк и N столбцов. Затем каждая ячейка представляется в виде маленького прямоугольника на сетке.

Зная все это, мы можем определить, какие клетки считать соседями данной ячейки. Для квадратной сетки двумя наиболее распространенными окрестностями являются:

  1. Район Мур (квадратная окрестность), как показано слева на рис. 2;
  2. район фон Неймана (ромбовидный), как показано справа на рис. 2.

Рис. 2: окрестности Мура и фон Неймана

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

Начальное условие, двумерная сетка, тип окрестности и правило обновления дают возникает бесконечное множество сценариев, которые трудно анализировать. По этой причине, мы сосредоточимся только на самом простом случае клеточных автоматов, а именно на элементарные клеточные автоматы

.

Элементарные клеточные автоматы

Элементарные клеточные автоматы являются простейшими нетривиальными автоматами. Они одномерны, означает, что есть только один ряд ячеек. Каждая ячейка имеет два возможных состояния (0 или 1), и ее соседями являются соседние ячейки по обе стороны от него, как показано на рисунке ниже:


Рис. 3: Элементарный клеточный автомат

Каждая ячейка с двумя соседними ячейками образует участок из 3-х ячеек, каждая из которых может иметь 2 состояния: либо 0, либо 1. {3} = 8 \) возможных вариантов: 000, 001, 010, 011, 100, 101, 110, 111 (числа от 0 до 7 в двоичном формате). 9{8} = 256 \) вариантов правила обновления. Следуя той же аналогии, это числа от 0 до 255 в двоичном формате. По этой причине правила обозначаются их порядковым номером.

Например, поскольку \( 150_{2} = 10010110 \), номер правила обновления 150 показан на рисунке ниже:


Рис. 4: Правило обновления 150

Далее мы увидим, как превратить это в реализацию Python и визуализацию с помощью Matplotlib.

Реализация Python

Первое, что нужно реализовать, это правило обновления. Учитывая состояние каждой ячейки в строке на некотором временном шаге T (обозначается как x ) и номер правила обновления, нам нужно получить состояние каждой ячейки в следующий временной шаг. Для этого мы используем следующий код:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20 
 импортировать numpy как np
power_of_two = np. array([[4], [2], [1]]) # форма (3, 1)
шаг определения (x, правило_бинарного):
    """Делает один шаг в клеточном автомате.
    Аргументы:
        x (np.array): текущее состояние автомата
        rule_binary (np.array): правило обновления
    Возвращает:
        np.array: обновленное состояние автомата
    """
    x_shift_right = np.roll(x, 1) # круговой сдвиг вправо
    x_shift_left = np.roll(x, -1) # циклический сдвиг влево
    y = np.vstack((x_shift_right, x, x_shift_left)).astype(np.int8) # стек построчно, форма (3, столбцы)
    z = np.sum(powers_of_two * y, axis=0).astype(np.int8) # Шаблон LCR в виде числа
    вернуть правило_двоичный [7 - z]
 

Сначала мы сдвигаем состояние каждой ячейки вправо, затем влево по кругу. Следующий, мы накладываем друг на друга левый сдвиг, текущий и правый сдвиг состояний ячеек. Это дает нам структуру, в которой каждый столбец имеет три элемента со значением либо 0, либо 1. Это означает что один столбец представляет одно число от 0 до 7 в двоичном формате. Мы используем это значение в качестве индекса в правило обновления, которое определяет следующее состояние центральной ячейки. Вся процедура расписана на рисунке ниже:


Рис. 5: Объяснение функции шаг

Имея правило обновления, остальная часть реализации довольно проста. Мы должны инициализировать клеточный автомат, а затем запустить его на заданное количество временных шагов. Реализация Python приведена ниже:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
3940
41
42
43 
 импортировать numpy как np
def cell_automaton (номер_правила, размер, шаги,
                       init_cond='случайный', pulse_pos='центр'):
    """Сгенерировать состояние элементарного клеточного автомата после заданного
    количество шагов, начиная с некоторого случайного состояния.
    Аргументы:
        rule_number (int): номер используемого правила обновления
        size (int): количество ячеек в строке
        steps (int): количество шагов для развития автомата
        init_cond (str): либо «случайный», либо «импульсный».
Если `случайно` каждая ячейка в строке активируется с помощью проб. 0,5. Если «импульсировать» только одну ячейку активирован. pulse_pos (str): если `init_cond` равно `impulse`, активируйте самая левая, центральная или самая правая ячейка. Возвращает: np.array: конечное состояние автомата """ утверждать 0 <= номер_правила <= 255 утверждать init_cond в ['случайный', 'импульсный'] утвердить pulse_pos в ['left', 'center', 'right'] rule_binary_str = np.binary_repr (номер_правила, ширина = 8) rule_binary = np.array([int(ch) для ch в rule_binary_str], dtype=np.int8) x = np.zeros((шаги, размер), dtype=np.int8) if init_cond == 'random': # случайная инициализация первого шага x[0,:] = np.array(np.random.rand(size) <0,5, dtype=np.int8) if init_cond == 'impulse': # начиная с начального импульса если pulse_pos == 'левый': х [0, 0] = 1 elif pulse_pos == 'правильно': х [0, размер - 1] = 1 еще: х[0, размер // 2] = 1 для я в диапазоне (шаги - 1): x[i + 1, :] = step(x[i, :], rule_binary) вернуть х

Теперь, используя этот код, мы можем легко построить график эволюции одного клеточного автомата во времени. Для клеточного автомата, который следует правилу номер 60, такому, что в начале только активна крайняя левая ячейка, эволюция автомата на первых 60 шагах изображена на рисунке ниже:


Рис. 6: Эволюция элементарного клеточного автомата

Анимированная визуализация

Давайте запустим в действие один клеточный автомат и посмотрим, как он будет выглядеть, когда он эволюционирует во времени. Для этого мы используем API Matplotlib Animation для создания анимации эволюции. процесс. Мы будем использовать правило № 90, начиная с одной активной ячейки в центре строки.

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


Рис. 7: Анимация эволюции элементарного клеточного автомата

Весь исходный код для реализации элементарных клеточных автоматов можно найти на Гитхаб.

Если это то, что вам нравится и вы хотели бы получать подобные сообщения, подпишитесь на список рассылки ниже. Для получения дополнительной информации, пожалуйста, следуйте за мной на LinkedIn или Твиттер.

Резюме: Элементарно, но не просто

Интересно наблюдать за повторяющимся рисунком треугольников в эволюции клеточного автомата выше. Тем не менее, это не всегда так. Например, доказано, что с помощью правило номер 110 мы можем получить полная по Тьюрингу машина это способно к универсальным вычислениям, что довольно ошеломительно для такой простой системы.

В заключение скажу, что элементарные клеточные автоматы и вообще клеточные автоматы — очень интересное явление. в мире вычислений. С помощью простого набора правил, мотивированных эволюцией живых организмов, можно построить универсальные машины, способные вычислить все.

Ссылки

[1] Стивен Вольфрам, «Новый вид науки» (2002 г. ), Wolfram Media

beamer - Рисование нескольких итераций клеточных автоматов в линию, возможно, с помощью TikZ - TeX

Я хочу проиллюстрировать итерации клеточного автомата картинка за картинкой в ​​некоторых слайды. Для тех, кто не знаком с этой темой, представьте себе двумерную сетку квадратных ячеек, где каждый квадрат в сетке может иметь «состояние» (которое будет представлено его цветом). На каждой итерации или временном шаге состояние клетки/квадрата меняется в зависимости от его окружения и текущего состояния — его цвет должен измениться на следующем изображении.

Кажется очевидным использование TikZ, поскольку он напрямую поддерживает рисование сеток, но часть, с которой я борюсь, заключается в том, чтобы придумать решение, позволяющее свести к минимуму усилия при окрашивании каждого отдельного квадрата, каждой отдельной итерации — ячейки (или «квадраты») менять состояние с каждым изображением, поэтому мне, по сути, приходилось бы раскрашивать каждый квадрат вручную для каждой итерации. Кажется, что много неприятного, неуправляемого кода будет неизбежно; По сути, я знаю, как решить свою проблему, но хотел спросить, есть ли (надеюсь) более разумный способ рисования/сделать это (надеюсь, что найдется около \foreach magic и прочее.)

Формулировка конкретных вопросов:

  1. Может уже есть пакет для рисования клеточных автоматов?
  2. Если нет, то есть ли более разумный способ использовать TikZ для рисования множества итераций клеточного автомата, чем вручную рисовать сетку и раскрашивать ее вручную?
  3. Если последние два вопроса слишком локализованы/сложны: существуют ли другие команды «структуры управления», похожие на \foreach , которые я мог бы использовать для рисования с использованием некоторых «правил», чтобы мне не нужно было раскрашивать каждый квадрат по рука?

Изучив ситуацию, насколько мне известно, я хочу попробовать реализацию с командой matrix в TikZ. Я определю матрицу пустых ячеек минимального размера и квадратных и изменю стиль узлов в соответствии с номером слайда. Это вполне может быть неоптимальным подходом, но, поскольку магия pgf, происходящая в ответе Марка Виброу, все еще почти не поддается расшифровке для меня, я думаю, что это лучший путь вперед.

Желаемое поведение автомата

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

  • Покоящаяся ячейка переходит в возбужденное состояние, если кто-то из ее соседей сам возбуждается.
  • Возбужденная клетка переходит в рефрактерную фазу.
  • Клетка в рефрактерной фазе переходит в состояние покоя, независимо от состояния его соседей.

Вот изображение того, как выглядит модель ( n - время, темная клетка возбуждается, полосатая - рефрактерная):

Я понимаю, что моя проблема сильно локализована, и не обращайте внимания если мне нужно адаптировать возможные ответы к моим целям, если они описывают общий способ решения проблемы; то, что я пытаюсь узнать, — это элегантные способы подчинить TikZ своей воле, поэтому эти ответы очень приветствуются.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *