
1
.docxМИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ
федеральное государственное автономное образовательное учреждение высшего образования
«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
АЭРОКОСМИЧЕСКОГО ПРИБОРОСТРОЕНИЯ»
Кафедра 41
ПРЕПОДАВАТЕЛЬ
Проф., д.-р физ.-мат. наук |
|
|
|
Ю. В. Рождественский |
должность, уч. степень, звание |
|
подпись, дата |
|
инициалы, фамилия |
Лабораторная работа №1
Имитационное моделирование с помощью клеточного автомата
по курсу: Имитационное моделирование
СТУДЕНТКА ГР. № |
Z0411 |
|
03.02.25 |
|
М. В. Карелина |
|
|
номер группы |
|
подпись, дата |
|
инициалы, фамилия |
Номер студенческого билета: 2020/3477
Санкт-Петербург
2025
Цель работы: на плоской сетке реализовать клеточный автомат на плоскости (т.н. игра "Жизнь"). Если возможно, придумать свои правила перехода к следующему поколению.
Ход работы:
В моем клеточном автомате описано противостояние клана Сенджу и клана Учиха из величайшего произведения современности «Наруто». В каждом клане по 25 человек. Противостояние происходит по следующим правилам:
2 клетки одного клана могут уничтожить 1 клетку другого клана
3 клетки клана Сенджу могут воскресить одну мертвую клетку Сенджу
Программный код моей реализации указан в Листинге 1.
Листинг 1.
import numpy as np import matplotlib.pyplot as plt import random import os # Настройки поля и клеток GRID_SIZE = 10 # Размер поля NUM_SENJU = 25 # Начальное количество клеток клана Сенджу NUM_UCHIHA = 25 # Начальное количество клеток клана Учиха GENERATIONS = 10 # Количество поколений # Определение клеток SENJU = 1 UCHIHA = 2 EMPTY = 0 DEAD_SENJU = 3 DEAD_UCHIHA = 4 # Создание директории для сохранения изображений image_dir = os.path.join(os.getcwd(), 'images') if not os.path.exists(image_dir): os.makedirs(image_dir) # Функция для создания начального состояния def initialize_grid(): grid = np.zeros((GRID_SIZE, GRID_SIZE), dtype=int) # Заполнение клана Сенджу for _ in range(NUM_SENJU): while True: x, y = random.randint(0, GRID_SIZE - 1), random.randint(0, GRID_SIZE - 1) if grid[x, y] == EMPTY: grid[x, y] = SENJU break # Заполнение клана Учиха for _ in range(NUM_UCHIHA): while True: x, y = random.randint(0, GRID_SIZE - 1), random.randint(0, GRID_SIZE - 1) if grid[x, y] == EMPTY: grid[x, y] = UCHIHA break return grid # Функция для визуализации текущего состояния def visualize_grid(grid, generation): plt.figure(figsize=(8, 8)) plt.imshow(grid, cmap='RdYlBu', vmin=0, vmax=4) plt.xticks([]) plt.yticks([]) plt.title(f"Поколение {generation}") cbar = plt.colorbar(ticks=[0, 1, 2, 3, 4], label='Состояние клеток') cbar.ax.set_yticklabels(['Пусто', 'Сенджу', 'Учиха', 'Труп Сенджу', 'Труп Учиха']) # Сохранение изображения в указанную папку plt.savefig(os.path.join(image_dir, f'generation_{generation}.png')) plt.close() # Закрытие графика после сохранения # Функция для выполнения одного поколения def step(grid): size = grid.shape[0] new_grid = np.copy(grid) # Создаем новую сетку для следующего поколения # Движение клеток for x in range(size): for y in range(size): if grid[x, y] in (SENJU, UCHIHA): directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)] random.shuffle(directions) # Перемешиваем направления moved = False for dx, dy in directions: nx, ny = x + dx, y + dy if 0 <= nx < size and 0 <= ny < size and new_grid[nx, ny] == EMPTY: new_grid[nx, ny] = grid[x, y] # Двигаем клетку new_grid[x, y] = EMPTY moved = True break # Выход из цикла, если движение успешно # Проверка на уничтожение клеток to_mark_dead = [] for x in range(size): for y in range(size): if new_grid[x, y] == SENJU: adjacent_uchiya = sum(new_grid[x + dx, y + dy] == UCHIHA for dx in [-1, 0, 1] for dy in [-1, 0, 1] if 0 <= x + dx < size and 0 <= y + dy < size) if adjacent_uchiya >= 2: to_mark_dead.append((x, y, DEAD_SENJU)) elif new_grid[x, y] == UCHIHA: adjacent_senju = sum(new_grid[x + dx, y + dy] == SENJU for dx in [-1, 0, 1] for dy in [-1, 0, 1] if 0 <= x + dx < size and 0 <= y + dy < size) if adjacent_senju >= 2: to_mark_dead.append((x, y, DEAD_UCHIHA)) # Обновляем статусы мертвых клеток for (i, j, status) in to_mark_dead: new_grid[i, j] = status # Воскрешение клеток Сенджу for x in range(size): for y in range(size): if new_grid[x, y] == DEAD_SENJU: # Проверяем только смерти Сенджу alive_senju_count = sum(new_grid[x + dx, y + dy] == SENJU for dx in [-1, 0, 1] for dy in [-1, 0, 1] if 0 <= x + dx < size and 0 <= y + dy < size) if alive_senju_count >= 3: # Условие воскрешения new_grid[x, y] = SENJU # Проверка на полное уничтожение клана alive_senju = np.sum(new_grid == SENJU) alive_uchiya = np.sum(new_grid == UCHIHA) if alive_senju == 0: # Если все Сенджу мертвы, добавляем 10 мертвых клеток for _ in range(10): while True: x, y = np.random.randint(0, size, 2) if new_grid[x, y] != UCHIHA and new_grid[x, y] != DEAD_SENJU: new_grid[x, y] = DEAD_SENJU break if alive_uchiya == 0: # Если все Учиха мертвы, добавляем 10 мертвых клеток for _ in range(10): while True: x, y = np.random.randint(0, size, 2) if new_grid[x, y] != SENJU and new_grid[x, y] != DEAD_UCHIHA: new_grid[x, y] = DEAD_UCHIHA break return new_grid # Функция для подсчета клеток def count_cells(grid): alive_senju = np.sum(grid == SENJU) dead_senju = np.sum(grid == DEAD_SENJU) alive_uchiya = np.sum(grid == UCHIHA) dead_uchiya = np.sum(grid == DEAD_UCHIHA) return alive_senju, dead_senju, alive_uchiya, dead_uchiya # Основная функция def main(): grid = initialize_grid() # Инициализация сетки for generation in range(GENERATIONS): visualize_grid(grid, generation) # Визуализация alive_senju, dead_senju, alive_uchiya, dead_uchiya = count_cells(grid) # Подсчет клеток print(f"Поколение {generation}:") print(f" Живые Сенджу: {alive_senju}, Мёртвые Сенджу: {dead_senju}") print(f" Живые Учиха: {alive_uchiya}, Мёртвые Учиха: {dead_uchiya}") # ШАГ: обновление сетки на следующем поколении grid = step(grid) if __name__ == "__main__": main()
Результат работы программы с 10 поколениями и размером сетки 10, представлены на рисунках 1 и 2. На рисунке 3 показаны числовые результаты.
Рисунок – 1. Поколение 0
Рисунок – 2. Поколение 9
Рисунок – 3. Результаты
Подведя итоги можно сказать что оба клана идут вровень по силе и численности убитых врагов.
Вывод
В данной работе был разработан клеточный автомат, который моделировал взаимодействие двух игровых кланов — Сенджу и Учиха — в формате клеточного автомата. Созданная модель отражает поведение и динамику данных кланов на основе заданных правил уничтожения и воскрешения клеток.
Клеточные автоматы (КА) — это математические модели, которые исследуют динамику взаимодействия объектов на дискретной решетке (двумерной или многомерной). КА состоят из клеток, каждая из которых может находиться в одном из конечного числа состояний. Их поведение определяется локальными правилами, которые определяют, как состояние каждой клетки зависит от состояний соседних клеток. Клеточные автоматы широко используются в различных областях науки и техники, включая физику, биологию, компьютерные науки и искусственный интеллект.
Клеточные автоматы представляют собой мощный инструмент для моделирования сложных динамических систем. Созданный клеточный автомат стал эффективным средством для моделирования взаимодействия между двумя кланами, иллюстрируя природу и динамику их конкуренции. Результаты работы показывают, что клеточные автоматы могут служить мощным средством для изучения взаимодействий в экосистемах и разработки стратегий в играх или биологических системах. Этот проект позволяет предполагать дальнейшее расширение, включая дополнительные правила и сложные взаимодействия, что сделает моделирование еще более увлекательным и познавательным.