Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

1

.docx
Скачиваний:
0
Добавлен:
16.05.2025
Размер:
115.54 Кб
Скачать

МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ

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

«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ

АЭРОКОСМИЧЕСКОГО ПРИБОРОСТРОЕНИЯ»

Кафедра 41

ПРЕПОДАВАТЕЛЬ

Проф., д.-р физ.-мат. наук

Ю. В. Рождественский

должность, уч. степень, звание

подпись, дата

инициалы, фамилия

Лабораторная работа №1

Имитационное моделирование с помощью клеточного автомата

по курсу: Имитационное моделирование

СТУДЕНТКА ГР. №

Z0411

03.02.25

М. В. Карелина

номер группы

подпись, дата

инициалы, фамилия

Номер студенческого билета: 2020/3477

Санкт-Петербург

2025

Цель работы: на плоской сетке реализовать клеточный автомат на плоскости (т.н. игра "Жизнь"). Если возможно, придумать свои правила перехода к следующему поколению.

Ход работы:

В моем клеточном автомате описано противостояние клана Сенджу и клана Учиха из величайшего произведения современности «Наруто». В каждом клане по 25 человек. Противостояние происходит по следующим правилам:

  1. 2 клетки одного клана могут уничтожить 1 клетку другого клана

  2. 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. Результаты

Подведя итоги можно сказать что оба клана идут вровень по силе и численности убитых врагов.

Вывод

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

Клеточные автоматы (КА) — это математические модели, которые исследуют динамику взаимодействия объектов на дискретной решетке (двумерной или многомерной). КА состоят из клеток, каждая из которых может находиться в одном из конечного числа состояний. Их поведение определяется локальными правилами, которые определяют, как состояние каждой клетки зависит от состояний соседних клеток. Клеточные автоматы широко используются в различных областях науки и техники, включая физику, биологию, компьютерные науки и искусственный интеллект.

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

Соседние файлы в предмете Имитационное моделирование