\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 > m\_field} -- двумерный вектор, представляющий текущее состояние клеточного автомата; \item \texttt{std::vector > 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> m_field; std::vector> 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(m_fieldWidth, 0)); m_fieldNextState.resize(m_fieldHeight, std::vector(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} \subsection{Пользовательский ввод} Одним из требований к лабораторным работам являлась защита от некорректного пользовательского ввода. Для реализации такой защиты и большей читаемости кода все функции связанные с пользовательским вводом были вынесены в отдельный файл. Все функции проверяют данные вводимые пользователем и, если что-то не так, печатают информацию о неверном выводе. \begin{itemize} \item {\tt int inputNumber(int minVal, int maxVal)} - принимает два числа, которые указывают диапозон возможных для ввода значений. Возвращает введённое пользователем число. \item {\tt char* inputString(int maxLen)} - принимает число, максимальную длину строки, возвращает указатель на строку введённую пользователем. Не позволяет вводить строки больше указанной длины. \item {\tt bool userApprove()} - возвращает true, если пользователь ввёл <> или <> и false, если пользователь ввёл <> или <>. \item {\tt void waitForEnter()} - останавливает выполнение программы пока пользователь не нажмёт на клавишу <>. \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}