Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 187 additions & 0 deletions Sergej_Narysev/Sergej_Narysev_report.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
\documentclass[a4paper]{article}

\usepackage[a4paper, top=8mm, bottom=8mm, left=8mm, right=8mm]{geometry}
\usepackage{float}
\usepackage{graphicx}

\usepackage{polyglossia}
\setdefaultlanguage[babelshorthands=true]{russian}
\setotherlanguage{english}

\usepackage{fontspec}
\setmainfont{FreeSerif}
\newfontfamily{\russianfonttt}[Scale=0.7]{DejaVuSansMono}

\usepackage[tiny, compact]{titlesec}

\usepackage{titling}
\setlength{\droptitle}{-1cm}
\pretitle{\begin{center}\begin{bfseries}\Large}
\posttitle{\par\end{bfseries}\end{center}}
\preauthor{\begin{center}\normalsize}
\postauthor{\par\end{center}\vspace{-1.8cm}}

\usepackage{hyperref}
\usepackage{bookmark}
\usepackage{csquotes}
\usepackage{booktabs}
\usepackage{multirow}

\title{Lamagraph: Разреженные матрицы на F\#}

\author{Нарышев Сергей Иванович}

\date{}

\begin{document}

\maketitle

\begin{flushright}
Группа: \emph{2025.Б-72-мм}

Кафедра: \emph{кафедра системного программирования}

Научный руководитель: \emph{Григорьев Семён Вячеславович}

Номер семестра практики: \emph{2}
\end{flushright}

\section{Введение}

Ключевую роль при работе с разрежёнными матрицами и векторами играет выбор эффективного внутреннего представления данных. Традиционные форматы вроде CSR (Compressed Sparse Row) обеспечивают высокую производительность статических операций, но плохо приспособлены к рекурсивным алгоритмам, характерным для функционального программирования. Альтернативный подход~--- использование деревьев квадрантов (quadtree), которые позволяют единообразно работать с данными на разных уровнях вложенности и естественным образом реализуют разрежённое хранение.

Библиотека QTreeFSharp~--- это реализация разрежённых векторов и матриц на основе деревьев квадрантов на языке F\#. Она предоставляет базовый набор операций линейной алгебры и алгоритмов анализа графов в парадигме Graph\-BLAS. В рамках данной работы выполнялось расширение функциональности библиотеки: добавлены операции фильтрации, проверки существования и всеобщности (\texttt{exists}, \texttt{forall}), необходимые для реализации более сложных графовых алгоритмов (например, выделение подмножества вершин по условию или проверка свойств графа без полного перебора).

\section{Цель и задачи}

\textbf{Целью работы} является доработка репозитория QTreeFSharp путём реализации трёх групп операций над разрежёнными структурами данных: фильтрации по предикату, проверки существования элемента, удовлетворяющего предикату, и проверки всеобщности.

Для достижения цели были поставлены следующие задачи.
\begin{enumerate}
\item Изучить внутреннее устройство библиотеки QTreeFSharp: типы данных деревьев квадрантов, механизм конденсации, существующие рекурсивные операции.
\item Реализовать операцию \texttt{filter} для векторов и матриц, возвращающую новую структуру, содержащую только элементы, удовлетворяющие предикату.
\item Реализовать операции \texttt{exists} и \texttt{forall} с поддержкой короткого замыкания для векторов и матриц.
\item Написать набор модульных тестов для проверки корректности реализованных операций.
\item Провести сравнительный анализ производительности реализованных операций на плотных и разрежённых данных.
\end{enumerate}

\section{Особенности реализации}

Векторы в библиотеке представлены бинарными деревьями: внутренний узел хранит два поддерева, лист~--- \texttt{Dummy} (не содержит данных, дополняет дерево до размера степени двойки) или \texttt{UserValue}~--- \texttt{Some(x)} либо \texttt{None} (ноль, определённый реализацией). Матрицы используют двумерные деревья квадрантов с четырьмя потомками (NW, NE, SW, SE). Для обеспечения компактности применяется конденсация: если после операции все четыре потомка узла стали одинаковыми листьями, они сливаются в один.

\texttt{filter} принимает структуру данных (вектор или матрицу) и функцию-предикат, после чего строит новую структуру, куда попадают только те элементы, для которых предикат вернул \texttt{true}. \texttt{Dummy}-листы игнорируются. Рекурсивный спуск по дереву позволяет обрабатывать только занятые узлы, а конденсация на выходе обеспечивает компактность результата. Это особенно важно для разрежённых данных, где большая часть элементов не удовлетворяет предикату~--- итоговая структура также остаётся разрежённой.

\texttt{exists} проверяет, встречается ли хотя бы один элемент, удовлетворяющий предикату (\texttt{||} по всем значениям). Если такой элемент найден, дальнейший обход дерева прекращается. \texttt{forall} проверяет, что все элементы удовлетворяют предикату (\texttt{\&\&} по всем значениям)~--- при нахождении первого неподходящего элемента обход также завершается досрочно. Короткое замыкание реализовано на уровне рекурсивного обхода: если левое поддерево уже дало ответ, правое не просматривается. В худшем случае (предикат истинен для всех элементов в exists или ни для одного в forall) выполняется полный обход, что эквивалентно filter.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему это не частные случаи какого-нибудь find?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

здесь всё таки проверяется, что какое то значение выполняется для хотя бы одного или для всех одновременно и возвращается булевое значение

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Для какого-нибудь --- это прям точно find. Для всех --- это отрицание find.


Для проверки корректности разработанных функций написаны модульные тесты (64 штуки). Они покрывают как штатные сценарии (фильтрация части элементов, exists/forall с подходящими и неподходящими предикатами), так и граничные случаи: пустые структуры, предикат, истинный для всех / ни для одного элемента, проверка досрочного завершения при коротком замыкании.

\section{Экспериментальная оценка}

В качестве инструмента профилирования использовался BenchmarkDotNet, среда исполнения~--- .NET 10. Для каждой операции измерялись математическое ожидание времени выполнения (Mean) и среднеквадратичное отклонение (StdDev).

Генерировались два набора синтетических данных:
\begin{itemize}
\item \textbf{Dense}~--- структуры, целиком заполненные единицами (максимальная нагрузка на дерево квадрантов);
\item \textbf{Sparse}~--- структуры с небольшим числом ненулевых элементов: около 3 на вектор и примерно 10 на каждую строку матрицы.
\end{itemize}

Тестирование проводилось для трёх размеров: 64, 256 и 1024. Для векторов размер означает длину, для квадратных матриц~--- количество строк и столбцов.

\begin{table}[H]
\centering
\caption{Результаты filter (среднее время, мкс)}
\label{tab:filter}
\begin{tabular}{lrrr}
\toprule
Метод & N=64 & N=256 & N=1024 \\
\midrule
VectorDense & 3 & 12 & 57 \\
VectorSparse & 1 & 5 & 20 \\
MatrixDense & 273 & 24\,400 & 402\,544 \\
MatrixSparse & 22 & 549 & 44\,189 \\
\bottomrule
\end{tabular}
\end{table}

\texttt{filter} рекурсивно обходит все узлы дерева, поэтому ожидается линейный рост для векторов ($O(N)$) и квадратичный для плотных матриц ($O(N^2)$). При увеличении N с 256 до 1024 время выросло в $\approx$5$\times$ для векторов и $\approx$17$\times$ для плотной матрицы, что согласуется с ожиданием. Разрежённые структуры растут медленнее, так как число ненулевых элементов линейно по N.

\begin{table}[H]
\centering
\caption{Результаты exists (среднее время, нс)}
\label{tab:exists}
\begin{tabular}{lrrr}
\toprule
Метод & N=64 & N=256 & N=1024 \\
\midrule
VectorDense & 527 & 2\,224 & 9\,440 \\
VectorSparse & 247 & 947 & 3\,899 \\
MatrixDense & 31\,292 & 579\,103 & 18\,688\,678 \\
MatrixSparse & 3\,769 & 57\,734 & 1\,274\,995 \\
\bottomrule
\end{tabular}
\end{table}

\begin{table}[H]
\centering
\caption{Результаты forall (среднее время, нс)}
\label{tab:forall}
\begin{tabular}{lrrr}
\toprule
Метод & N=64 & N=256 & N=1024 \\
\midrule
VectorDense & 556 & 2\,212 & 9\,207 \\
VectorSparse & 258 & 978 & 4\,148 \\
MatrixDense & 33\,393 & 625\,096 & 19\,155\,156 \\
MatrixSparse & 4\,155 & 60\,387 & 1\,429\,950 \\
\bottomrule
\end{tabular}
\end{table}

На рис.~\ref{fig:forall_vect} и~\ref{fig:forall_mat} приведено визуальное сравнение exists и forall.

\begin{figure}[H]
\centering
\includegraphics[width=0.92\textwidth]{images/forall_vs_exists_vector.pdf}
\caption{Сравнение exists/forall на векторах}
\label{fig:forall_vect}
\end{figure}

\begin{figure}[H]
\centering
\includegraphics[width=0.92\textwidth]{images/forall_vs_exists_matrix.pdf}
\caption{Сравнение exists/forall на матрицах (N=64, 256)}
\label{fig:forall_mat}
\end{figure}

\begin{figure}[H]
\centering
\includegraphics[width=0.92\textwidth]{images/filters_combined.pdf}
\caption{Производительность filter на различных размерах и типах данных}
\label{fig:filters}
\end{figure}

\texttt{exists} и \texttt{forall} в худшем случае (полный обход) имеют ту же асимптотику, что и filter: $O(N)$ для векторов, $O(N^2)$ для плотных матриц. Разница между ними находится в пределах погрешности. При срабатывании короткого замыкания (первый же подходящий элемент в exists или неподходящий в forall) сложность падает до $O(1)$. Выигрыш разрежённого представления (до 3$\times$ для векторов и до 15$\times$ для матриц) объясняется меньшим числом обходимых узлов.

\section{Заключение}

В ходе выполнения работы получены следующие результаты:

\begin{itemize}
\item Реализованы операции \texttt{filter}, \texttt{exists} и \texttt{forall} для разрежённых векторов и матриц на основе деревьев квадрантов.
\item В \texttt{exists} и \texttt{forall} внедрено короткое замыкание, позволяющее завершать обход досрочно.
\item Написаны 64 модульных теста для проверки корректности реализованных функций.
\item Проведены бенчмарки, подтверждающие ожидаемую масштабируемость: рост времени соответствует полному обходу дерева ($O(N)$ для векторов, $O(N^2)$ для матриц); выигрыш разрежённого представления~--- до $15\times$.
\end{itemize}

\begin{thebibliography}{99}
\bibitem{qtreefsharp} Репозиторий QTreeFSharp. URL: \url{https://github.com/Lamagraph/QTreeFSharp}
\bibitem{benchmarkdotnet} BenchmarkDotNet. URL: \url{https://benchmarkdotnet.org/}
\bibitem{fsharpdocs} F Sharp Programming. URL: \url{https://en.wikibooks.org/wiki/F_Sharp_Programming}
\bibitem{matplotlib} Matplotlib documentation. URL: \url{https://matplotlib.org/stable/contents.html}
\end{thebibliography}

\section{Репозиторий}
\url{https://github.com/narysh/QTreeFSharp}

\end{document}
Binary file added Sergej_Narysev/images/filters_combined.pdf
Binary file not shown.
Binary file added Sergej_Narysev/images/forall_vs_exists_matrix.pdf
Binary file not shown.
Binary file added Sergej_Narysev/images/forall_vs_exists_vector.pdf
Binary file not shown.
5 changes: 3 additions & 2 deletions main.tex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
\usepackage[en-US]{datetime2}

\usepackage{polyglossia}
% Setup fonts.
\usepackage{fontspec}
\setmainfont{CMU Serif}
\setsansfont{CMU Sans Serif}
Expand All @@ -13,7 +12,6 @@

\setdefaultlanguage{russian}


\begin{document}
Compiled: \DTMnow
\tableofcontents
Expand Down Expand Up @@ -65,4 +63,7 @@
\includepdf[pages=-,
addtotoc={1, section, 1, {Арзамасцева Екатерина Андреевна, Оптимизация произведения Кронекера для библиотеки SuiteSparse:GraphBLAS}, arzamaszeva_ekaterina}]
{Ekaterina_Arzamaszeva/Ekaterina_Arzamaszeva_report.pdf}
\includepdf[pages=-,
addtotoc={1, section, 1, {Нарышев Сергей Иванович, Lamagraph: Разреженные матрицы на F\#}, naryshev_sergej}]
{Sergej_Narysev/Sergej_Narysev_report.pdf}
\end{document}