446 lines
24 KiB
TeX
446 lines
24 KiB
TeX
\documentclass[a4paper, final]{article}
|
||
%\usepackage{literat} % Нормальные шрифты
|
||
\usepackage[14pt]{extsizes} % для того чтобы задать нестандартный 14-ый размер шрифта
|
||
\usepackage[T2A]{fontenc}
|
||
\usepackage[utf8]{inputenc}
|
||
\usepackage[russian]{babel}
|
||
\usepackage{amsmath}
|
||
\usepackage[left=25mm, top=20mm, right=20mm, bottom=20mm, footskip=10mm]{geometry}
|
||
\usepackage{ragged2e} %для растягивания по ширине
|
||
\usepackage{setspace} %для межстрочного интервала
|
||
\usepackage{moreverb} %для работы с листингами
|
||
\usepackage{indentfirst} % для абзацного отступа
|
||
\usepackage{moreverb} %для печати в листинге исходного кода программ
|
||
\usepackage{graphicx}
|
||
|
||
\usepackage{array}
|
||
\usepackage{multirow}
|
||
|
||
\renewcommand\verbatimtabsize{4\relax}
|
||
\renewcommand\listingoffset{0.2em} %отступ от номеров строк в листинге
|
||
\renewcommand{\arraystretch}{1.4} % изменяю высоту строки в таблице
|
||
\usepackage[font=small, singlelinecheck=false, justification=centering, format=plain, labelsep=period]{caption} %для настройки заголовка таблицы
|
||
\usepackage{listings} %листинги
|
||
\usepackage{xcolor} % цвета
|
||
\usepackage{hyperref}% для гиперссылок
|
||
\usepackage{enumitem} %для перечислений
|
||
\newtheorem{theorem}{Теорема} % Создание нового окружения для теорем
|
||
\setlist[enumerate,itemize]{leftmargin=1.2cm} %отступ в перечислениях
|
||
|
||
\hypersetup{colorlinks,
|
||
allcolors=[RGB]{010 090 200}} %красивые гиперссылки (не красные)
|
||
|
||
% подгружаемые языки — подробнее в документации listings (это всё для листингов)
|
||
\lstloadlanguages{ C++}
|
||
% включаем кириллицу и добавляем кое−какие опции
|
||
\lstset{tabsize=2,
|
||
breaklines,
|
||
basicstyle=\footnotesize,
|
||
columns=fullflexible,
|
||
flexiblecolumns,
|
||
numbers=left,
|
||
numberstyle={\footnotesize},
|
||
keywordstyle=\color{blue},
|
||
inputencoding=cp1251,
|
||
extendedchars=true
|
||
}
|
||
\lstdefinelanguage{MyC}{
|
||
language=C++,
|
||
% ndkeywordstyle=\color{darkgray}\bfseries,
|
||
% identifierstyle=\color{black},
|
||
% morecomment=[n]{/**}{*/},
|
||
% commentstyle=\color{blue}\ttfamily,
|
||
% stringstyle=\color{red}\ttfamily,
|
||
% morestring=[b]",
|
||
% showstringspaces=false,
|
||
% morecomment=[l][\color{gray}]{//},
|
||
keepspaces=true,
|
||
escapechar=\%,
|
||
texcl=true
|
||
}
|
||
|
||
\textheight=24cm % высота текста
|
||
\textwidth=16cm % ширина текста
|
||
\oddsidemargin=0pt % отступ от левого края
|
||
\topmargin=-1.5cm % отступ от верхнего края
|
||
\parindent=24pt % абзацный отступ
|
||
\parskip=5pt % интервал между абзацами
|
||
\tolerance=2000 % терпимость к "жидким" строкам
|
||
\flushbottom % выравнивание высоты страниц
|
||
|
||
|
||
% Настройка листингов
|
||
\lstset{
|
||
language=C++,
|
||
extendedchars=\true,
|
||
inputencoding=utf8,
|
||
keepspaces=true,
|
||
% captionpos=b,
|
||
}
|
||
|
||
\begin{document} % начало документа
|
||
|
||
% НАЧАЛО ТИТУЛЬНОГО ЛИСТА
|
||
\begin{center}
|
||
\hfill \break
|
||
\hfill \break
|
||
\normalsize{МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ\\
|
||
федеральное государственное автономное образовательное учреждение высшего образования «Санкт-Петербургский политехнический университет Петра Великого»\\[10pt]}
|
||
\normalsize{Институт компьютерных наук и кибербезопасности}\\[10pt]
|
||
\normalsize{Высшая школа технологий искусственного интеллекта}\\[10pt]
|
||
\normalsize{Направление: 02.03.01 <<Математика и компьютерные науки>>}\\
|
||
|
||
\hfill \break
|
||
\hfill \break
|
||
\hfill \break
|
||
\hfill \break
|
||
\large{Отчет по лабораторной работе №1}\\
|
||
\large{<<Реализация двумерного клеточного автомата>>}\\
|
||
\large{по дисциплине <<Теория алгоритмов>>}\\
|
||
\large{Вариант 25}\\
|
||
|
||
\hfill \break
|
||
\hfill \break
|
||
\end{center}
|
||
|
||
\small{
|
||
\begin{tabular}{lrrl}
|
||
\!\!\!Студент, & \hspace{2cm} & & \\
|
||
\!\!\!группы 5130201/20102 & \hspace{2cm} & \underline{\hspace{3cm}} &Тищенко А. А. \\\\
|
||
\!\!\!Преподаватель & \hspace{2cm} & \underline{\hspace{3cm}} & Востров А. В. \\\\
|
||
&&\hspace{4cm}
|
||
\end{tabular}
|
||
\begin{flushright}
|
||
<<\underline{\hspace{1cm}}>>\underline{\hspace{2.5cm}} 2024г.
|
||
\end{flushright}
|
||
}
|
||
|
||
\hfill \break
|
||
% \hfill \break
|
||
\begin{center} \small{Санкт-Петербург, 2024} \end{center}
|
||
\thispagestyle{empty} % выключаем отображение номера для этой страницы
|
||
|
||
% КОНЕЦ ТИТУЛЬНОГО ЛИСТА
|
||
\newpage
|
||
|
||
\tableofcontents
|
||
|
||
\newpage
|
||
|
||
\section*{Введение}
|
||
\addcontentsline{toc}{section}{Введение}
|
||
Лабораторная работа заключалась в следующем:
|
||
|
||
\begin{itemize}
|
||
\item Реализовать двумерный клеточный автомат с окрестностью фон Неймана в соответствии с полученным номером (№109063350), который задаёт функцию перехода автомата.
|
||
\item Предложить самостоятельно граничные условия (тороидальные, нулевые, единичные).
|
||
\item Обеспечить возможность пользователю задавать ширину поля и количество итераций.
|
||
\item Учесть возможность ввода различных начальных условий (как вручную, так и случайным образом) по выбору пользователя.
|
||
\item Реализовать автомат в консольном или графическом интерфейсе.
|
||
\item Проанализировать поведение клеточного автомата, выявить паттерны, оценить "сходимость" и другие характеристики в отчете.
|
||
\end{itemize}
|
||
|
||
\newpage
|
||
|
||
\section {Математическое описание}
|
||
|
||
|
||
\newpage
|
||
\section{Особенности реализации}
|
||
\subsection{Класс CellularAutomaton}
|
||
В листинге~\ref{lst:CellularAutomaton} представлен код объявления класса \texttt{CellularAutomaton}.
|
||
|
||
Класс содержит следующие атрибуты:
|
||
\begin{itemize}
|
||
\item \texttt{static const unsigned int m\_functionValues} -- хранит число, соответствующее номеру варианта лабораторной работы, его битовое представление соответствует функции переходов двумерного клеточного автомата;
|
||
\item \texttt{int m\_fieldWidth} -- ширина поля клеточного автомата;
|
||
\item \texttt{int m\_fieldHeight} -- высота поля клеточного автомата;
|
||
\item \texttt{std::vector<std::vector<int> > m\_field} -- двумерный вектор, представляющий текущее состояние клеточного автомата;
|
||
\item \texttt{std::vector<std::vector<int> > m\_fieldNextState} -- двумерный вектор для хранения следующего состояния клеточного автомата;
|
||
\item \texttt{BoundaryCondition m\_boundaryCondition} -- граничные условия, задаются значением из перечисления \texttt{BoundaryCondition}.
|
||
\end{itemize}
|
||
|
||
Перечисление \texttt{BoundaryCondition} имеет три возможных значения:
|
||
\begin{itemize}
|
||
\item \texttt{BOUNDARY\_ONES} -- единичные граничные условия;
|
||
\item \texttt{BOUNDARY\_ZEROS} -- нулевые граничные условия;
|
||
\item \texttt{BOUNDARY\_TOROIDAL} -- тороидальные граничные условия.
|
||
\end{itemize}
|
||
|
||
Методы класса описываются в последующих разделах.
|
||
|
||
\begin{lstlisting}[caption={Код объявления класса CellularAutomaton.}, label={lst:CellularAutomaton}]
|
||
enum BoundaryCondition {
|
||
BOUNDARY_ONES,
|
||
BOUNDARY_ZEROS,
|
||
BOUNDARY_TOROIDAL
|
||
};
|
||
|
||
class CellularAutomaton
|
||
{
|
||
static const unsigned int m_functionValues = 25 * 11 * 2003 * 18 * 11;
|
||
|
||
int m_fieldWidth, m_fieldHeight;
|
||
std::vector<std::vector<int>> m_field;
|
||
std::vector<std::vector<int>> m_fieldNextState;
|
||
BoundaryCondition m_boundaryCondition;
|
||
|
||
void initializeRandom();
|
||
void initializeManual();
|
||
|
||
int getCellState(int x, int y) const;
|
||
int getNeighborhoodIndex(int x, int y) const;
|
||
public:
|
||
CellularAutomaton(int width, int height, bool fillWithRandom, BoundaryCondition boundaryCondition);
|
||
|
||
void update();
|
||
void displayField() const;
|
||
};
|
||
\end{lstlisting}
|
||
|
||
\subsubsection{Конструктор CellularAutomaton}
|
||
|
||
Конструктор класса CellularAutomaton, код которого представлен в листиге~\ref{lst:CellularAutomatonConstructor}, принимает следующие параметры:
|
||
\begin{itemize}
|
||
\item \texttt{int width} -- ширина поля клеточного автомата;
|
||
\item \texttt{int height} -- высота поля клеточного автомата;
|
||
\item \texttt{bool fillWithRandom} -- флаг, определяющий, инициализировать ли поле случайными значениями;
|
||
\item \texttt{BoundaryCondition boundaryCondition} -- условие на границе поля.
|
||
\end{itemize}
|
||
|
||
Конструктор создает объект \texttt{CellularAutomaton} с заданными размерами и граничными условиями. Если \texttt{fillWithRandom} равно \texttt{true}, то поле инициализируется случайным образом с помощью метода \texttt{initializeRandom}, иначе пользователь может вручную ввести начальное состояние с помощью метода \texttt{initializeManual}.
|
||
|
||
\begin{lstlisting}[caption={Код конструктора CellularAutomaton.}, label={lst:CellularAutomatonConstructor}]
|
||
CellularAutomaton::CellularAutomaton(int width, int height, bool fillWithRandom, BoundaryCondition boundaryCondition)
|
||
: m_fieldWidth(width), m_fieldHeight(height), m_boundaryCondition(boundaryCondition)
|
||
{
|
||
m_field.resize(m_fieldHeight, std::vector<int>(m_fieldWidth, 0));
|
||
m_fieldNextState.resize(m_fieldHeight, std::vector<int>(m_fieldWidth, 0));
|
||
|
||
if (fillWithRandom) initializeRandom();
|
||
else initializeManual();
|
||
}
|
||
\end{lstlisting}
|
||
|
||
\subsubsection{Метод initializeRandom}
|
||
В листинге~\ref{lst:initializeRandom} представлен код метода \texttt{initializeRandom}. Метод явно ничего не принимает и не возвращает, а работает только с атрибутами класса \texttt{CellularAutomaton}. В результате его работы атрибут \texttt{m\_field} заполняется нулями и единицами случайным образом, для этого используется равномерное распределение.
|
||
|
||
\begin{lstlisting}[caption={Код метода initializeRandom.}, label={lst:initializeRandom}]
|
||
void CellularAutomaton::initializeRandom()
|
||
{
|
||
std::random_device rd;
|
||
std::mt19937 gen(rd());
|
||
std::uniform_int_distribution<> dis(0, 1);
|
||
|
||
for (int y = 0; y < m_fieldHeight; ++y)
|
||
{
|
||
for (int x = 0; x < m_fieldWidth; ++x)
|
||
{
|
||
m_field[y][x] = dis(gen);
|
||
}
|
||
}
|
||
}
|
||
\end{lstlisting}
|
||
|
||
\subsubsection{Метод initializeManual}
|
||
В листинге~\ref{lst:initializeManual} представлен код метода \texttt{initializeManual}. Метод не принимает аргументов и ничего не возвращает. Он позволяет пользователю вручную ввести начальное состояние поля клеточного автомата. Для каждой клетки запрашивается значение 0 или 1, которые сохраняются в атрибуте \texttt{m\_field}.
|
||
|
||
\begin{lstlisting}[caption={Код метода initializeManual.}, label={lst:initializeManual}]
|
||
void CellularAutomaton::initializeManual()
|
||
{
|
||
std::cout << "Введите начальное состояние поля (" << m_fieldWidth << " x " << m_fieldHeight << ").\n";
|
||
std::cout << "Введите 0 или 1 для каждой клетки.\n";
|
||
|
||
for (int y = 0; y < m_fieldHeight; ++y)
|
||
{
|
||
for (int x = 0; x < m_fieldWidth; ++x)
|
||
{
|
||
std::cout << "Клетка (" << x << ", " << y << "): ";
|
||
int cellValue = inputNumber(0, 1);
|
||
|
||
m_field[y][x] = cellValue;
|
||
}
|
||
}
|
||
}
|
||
\end{lstlisting}
|
||
|
||
\subsubsection{Метод getCellState}
|
||
В листинге~\ref{lst:getCellState} представлен код метода \texttt{getCellState}. Метод принимает на вход координаты клетки \texttt{int x} и \texttt{int y}. Возвращает \texttt{int} -- состояние клетки по указанным координатам. Если координаты выходят за пределы поля, то поведение определяется граничными условиями, заданными атрибутом \texttt{m\_boundaryCondition}.
|
||
|
||
\begin{lstlisting}[caption={Код метода getCellState.}, label={lst:getCellState}]
|
||
int CellularAutomaton::getCellState(int x, int y) const
|
||
{
|
||
if (x < 0 || x >= m_fieldWidth || y < 0 || y >= m_fieldHeight)
|
||
{
|
||
switch (m_boundaryCondition)
|
||
{
|
||
case BOUNDARY_ONES:
|
||
return 1;
|
||
case BOUNDARY_ZEROS:
|
||
return 0;
|
||
case BOUNDARY_TOROIDAL:
|
||
x = (x + m_fieldWidth) % m_fieldWidth;
|
||
y = (y + m_fieldHeight) % m_fieldHeight;
|
||
return m_field[y][x];
|
||
default:
|
||
return 0;
|
||
}
|
||
}
|
||
return m_field[y][x];
|
||
}
|
||
\end{lstlisting}
|
||
|
||
\subsubsection{Метод getNeighborhoodIndex}
|
||
В листинге~\ref{lst:getNeighborhoodIndex} представлен код метода \texttt{getNeighborhoodIndex}. Метод принимает на вход координаты клетки \texttt{int x} и \texttt{int y}. Возвращает \texttt{int} -- индекс конфигурации окрестности фон Неймана клетки. Индекс вычисляется на основе состояний центральной клетки и её четырёх соседей (сверху, снизу, слева и справа), где каждый сосед соответствует одному биту в индексе. Этот индекс используется для определения следующего состояния клетки по функции переходов в методе \texttt{update}.
|
||
|
||
\begin{lstlisting}[caption={Код метода getNeighborhoodIndex.}, label={lst:getNeighborhoodIndex}]
|
||
int CellularAutomaton::getNeighborhoodIndex(int x, int y) const
|
||
{
|
||
int s0 = getCellState(x, y);
|
||
int s1 = getCellState(x, y - 1);
|
||
int s2 = getCellState(x, y + 1);
|
||
int s3 = getCellState(x - 1, y);
|
||
int s4 = getCellState(x + 1, y);
|
||
|
||
int index = (s0 << 4) | (s1 << 3) | (s2 << 2) | (s3 << 1) | s4;
|
||
|
||
return index;
|
||
}
|
||
\end{lstlisting}
|
||
|
||
\subsubsection{Метод update}
|
||
В листинге~\ref{lst:update} представлен код метода \texttt{update}. Метод не принимает аргументов и ничего не возвращает. Он обновляет состояние клеточного автомата на следующий временной шаг. Для каждой клетки вычисляется новое состояние на основе текущего состояния и функции переходов, значения которой хранятся в битах числа \texttt{m\_functionValues}. После вычисления новое состояние сохраняется в \texttt{m\_fieldNextState}, а затем происходит обмен содержимого \texttt{m\_field} и \texttt{m\_fieldNextState}.
|
||
|
||
\begin{lstlisting}[caption={Код метода update.}, label={lst:update}]
|
||
void CellularAutomaton::update()
|
||
{
|
||
for (int y = 0; y < m_fieldHeight; ++y)
|
||
{
|
||
for (int x = 0; x < m_fieldWidth; ++x)
|
||
{
|
||
int neighborhood = getNeighborhoodIndex(x, y);
|
||
m_fieldNextState[y][x] = (m_functionValues >> neighborhood) & 1;
|
||
}
|
||
}
|
||
|
||
m_field.swap(m_fieldNextState);
|
||
}
|
||
\end{lstlisting}
|
||
|
||
\subsubsection{Метод displayField}
|
||
В листинге~\ref{lst:displayField} представлен код метода \texttt{displayField}. Метод не принимает аргументов и ничего не возвращает. Он выводит текущее состояние поля клеточного автомата в консоль, отображая каждую клетку как '0' или '1'.
|
||
|
||
\begin{lstlisting}[caption={Код метода displayField.}, label={lst:displayField}]
|
||
void CellularAutomaton::displayField() const
|
||
{
|
||
for (const auto& row : m_field)
|
||
{
|
||
for (const auto& cell : row)
|
||
{
|
||
std::cout << (cell ? '1' : '0') << ' ';
|
||
}
|
||
std::cout << '\n';
|
||
}
|
||
}
|
||
\end{lstlisting}
|
||
|
||
|
||
\subsection{Функция main}
|
||
В функции main, код которой представлен в листинге~\ref{lst:main}, содержится бесконечный цикл, который обрабатывает пользовательский ввод. На каждой итерации цикла, пользователю предлагается выбрать конфигурацию конечного двумерного автомата и количество итераций. Затем внутри функции создаётся объект класса \texttt{CellularAutomaton}, с заданными пользователем параметрами, и у него вызывается метод \texttt{update} согласно указанному количеству итераций. Функция \texttt{main} возвращает целое число, которое является кодом завершения программы - 0, если программа выполнилась успешно, и ненулевое значение, если произошла какая-либо ошибка.
|
||
|
||
|
||
\begin{lstlisting}[caption={Код функции main.}, label={lst:main}]
|
||
int main()
|
||
{
|
||
setlocale(LC_ALL, "Russian");
|
||
|
||
while (true) {
|
||
clear();
|
||
|
||
cout << "Выберите граничные условия:\n"
|
||
"Единичные (0)\n"
|
||
"Нулевые (1)\n"
|
||
"Торроидальные (2)\n"
|
||
"Завершить работу (3)\n\n";
|
||
int actionId = inputNumber(0, 3);
|
||
|
||
clear();
|
||
|
||
if (actionId == 3) {
|
||
cout << "Выйти из программы? (yes/no)\n";
|
||
if (userApprove()) return 0;
|
||
continue;
|
||
}
|
||
|
||
BoundaryCondition boundaryCondition = static_cast<BoundaryCondition>(actionId);
|
||
|
||
cout << "Укажите ширину поля (min 1): ";
|
||
int fieldWidth = inputNumber(1);
|
||
|
||
cout << "Укажите высоту поля (min 1): ";
|
||
int fieldHeight = inputNumber(1);
|
||
|
||
cout << "Укажите количество итераций (min 1): ";
|
||
int iterationsCount = inputNumber(1);
|
||
|
||
cout << "Заполнить поле случайными значениями? (yes/no)\n";
|
||
bool fillWithRandom = userApprove();
|
||
|
||
CellularAutomaton ca(fieldWidth, fieldHeight, fillWithRandom, boundaryCondition);
|
||
clear();
|
||
|
||
cout << "\nИтерация 0:\n";
|
||
ca.displayField();
|
||
|
||
for (int i = 0; i < iterationsCount; ++i)
|
||
{
|
||
cout << "\nИтерация " << i + 1 << ":\n";
|
||
ca.update();
|
||
ca.displayField();
|
||
}
|
||
|
||
cout << "\nНажмите на enter, чтобы продолжить...";
|
||
waitForEnter();
|
||
}
|
||
}
|
||
\end{lstlisting}
|
||
|
||
\subsection{Пользовательский ввод}
|
||
Одним из требований к лабораторным работам являлась защита от некорректного пользовательского ввода. Для реализации такой защиты и большей читаемости кода все функции связанные с пользовательским вводом были вынесены в отдельный файл. Все функции проверяют данные вводимые пользователем и, если что-то не так, печатают информацию о неверном выводе.
|
||
|
||
\begin{itemize}
|
||
\item {\tt int inputNumber(int minVal, int maxVal)} - принимает два числа, которые указывают диапозон возможных для ввода значений. Возвращает введённое пользователем число.
|
||
\item {\tt char* inputString(int maxLen)} - принимает число, максимальную длину строки, возвращает указатель на строку введённую пользователем. Не позволяет вводить строки больше указанной длины.
|
||
\item {\tt bool userApprove()} - возвращает true, если пользователь ввёл <<yes>> или <<y>> и false, если пользователь ввёл <<no>> или <<n>>.
|
||
\item {\tt void waitForEnter()} - останавливает выполнение программы пока пользователь не нажмёт на клавишу <<Enter>>.
|
||
\end{itemize}
|
||
|
||
|
||
\newpage
|
||
\section {Результаты работы программы}
|
||
|
||
В данном разделе представлены скриншоты с примерами ввода-вывода, демонстрирующие работу программы и её основной функционал.
|
||
|
||
На Рис.~\ref{fig:menu1} показано основное меню программы, в котором перечислены доступные пользователю действия.
|
||
|
||
|
||
\newpage
|
||
\section*{Заключение}
|
||
|
||
\addcontentsline{toc}{section}{Заключение}
|
||
|
||
В результате выполнения лабораторной работы было разработано консольное приложение, ...
|
||
|
||
|
||
\newpage
|
||
\section*{Список литературы}
|
||
\addcontentsline{toc}{section}{Список литературы}
|
||
|
||
\vspace{-1.5cm}
|
||
\begin{thebibliography}{0}
|
||
\bibitem{vostrov}
|
||
Востров А. В, <<Теория алгоритмов>> URL: \url{https://tema.spbstu.ru/algorithm/}, Дата обращения: 01.12.2024
|
||
\bibitem{novikov}
|
||
Новиков, Ф. А. <<Дискретная математика для программистов>>. — 3-е изд. — Санкт-Петербург: Питер, 2009. — 383 с.
|
||
\end{thebibliography}
|
||
\end{document} |