From df84abe665a5c711a126844d352eedfb14eb74ad Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sat, 8 Jun 2024 13:34:59 +0300 Subject: [PATCH 01/29] Remove all --- tex/CFPQ_to_Datalog.tex | 142 -- tex/CYK_for_CFPQ.tex | 732 ------ tex/CombinatorsForCFPQ.tex | 28 - tex/Conclusion.tex | 7 - tex/ConjunctiveAndBooleanLanguages.tex | 235 -- tex/Context-Free_Languages.tex | 588 ----- tex/DerivativesForCFPQ.tex | 156 -- tex/FLPQ.tex | 146 -- ...ageConstrainedReachabilityLectureNotes.bib | 1984 ----------------- ...ageConstrainedReachabilityLectureNotes.tex | 204 -- tex/FormalLanguageTheoryIntro.tex | 297 --- tex/GLL-based_CFPQ.tex | 647 ------ tex/GLR-based_CFPQ.tex | 1159 ---------- tex/GraphTheoryIntro.tex | 538 ----- tex/Introduction.tex | 78 - tex/LinearAlgebra.tex | 774 ------- tex/List_of_contributors.tex | 30 - tex/Matrix-based_CFPQ.tex | 367 --- ...ple_Context-Free_Language_Reachability.tex | 401 ---- tex/Multiple_Context-Free_Languages.tex | 207 -- tex/Project.tex | 0 tex/RPQ.tex | 669 ------ tex/RegularLanguages.tex | 263 --- tex/SPPF.tex | 717 ------ tex/TensorProduct.tex | 1366 ------------ tex/figures/Chomsky.pdf | Bin 14109 -> 0 bytes tex/figures/Chomsky.svg | 115 - tex/figures/GLR/CLR_example.tex | 99 - tex/figures/GLR/GLR_example.tex | 101 - tex/figures/GLR/LL_LR.tex | 21 - tex/figures/GLR/LR0/complete.tex | 67 - tex/figures/GLR/LR0/state0.tex | 14 - tex/figures/GLR/LR0/state1.tex | 23 - tex/figures/GLR/LR0/state2.tex | 29 - tex/figures/GLR/LR0/state3.tex | 42 - tex/figures/GLR/LR0/state4.tex | 48 - tex/figures/GLR/LR0/state5.tex | 62 - tex/figures/cfl/pumping0.tex | 26 - tex/figures/cfl/pumping1.tex | 34 - tex/figures/cfl/pumping2.tex | 40 - tex/figures/cfl/tree0.tex | 27 - tex/figures/cyk/graph1.tex | 19 - tex/figures/flpq/path1.tex | 8 - tex/figures/flpq/path2.tex | 12 - tex/figures/gll/complete.tex | 26 - tex/figures/gll/state0.tex | 3 - tex/figures/gll/state1.tex | 8 - tex/figures/gll/state2.tex | 10 - tex/figures/gll/state3.tex | 13 - tex/figures/gll/state4.tex | 15 - tex/figures/gll/state5.tex | 17 - tex/figures/gll/state6.tex | 19 - tex/figures/gll/state7.tex | 22 - tex/figures/gll/state8.tex | 24 - tex/figures/graph/graph0.tex | 19 - tex/figures/graph/graph1.tex | 18 - tex/figures/graph/graph2.tex | 19 - tex/figures/graph/graph3.tex | 20 - tex/figures/graph/graph4.tex | 19 - tex/figures/graph/graph5.tex | 31 - tex/figures/graph/graph_BFS_1.tex | 19 - tex/figures/graph/graph_BFS_2.tex | 19 - tex/figures/graph/graph_BFS_3.tex | 19 - tex/figures/graph/graph_MS-BFS_1.tex | 19 - tex/figures/graph/graph_MS-BFS_2.tex | 19 - tex/figures/graph/path0.tex | 6 - tex/figures/mcfg/mcfg.pdf | Bin 6679 -> 0 bytes tex/figures/mcfg/mcfg.svg | 164 -- tex/figures/mcfg/mcfg_2.pdf | Bin 6053 -> 0 bytes tex/figures/mcfg/mcfg_2.svg | 157 -- tex/figures/multi/graph0.tex | 18 - tex/figures/tensor/graph0.tex | 20 - tex/figures/tensor/graph1.tex | 21 - tex/figures/tensor/graph2.tex | 21 - tex/figures/tensor/graph3.tex | 21 - tex/figures/tensor/graph4.tex | 22 - tex/figures/tensor/graph5.tex | 23 - tex/figures/tensor/recursive.tex | 16 - tex/makefile | 9 - 79 files changed, 13398 deletions(-) delete mode 100644 tex/CFPQ_to_Datalog.tex delete mode 100644 tex/CYK_for_CFPQ.tex delete mode 100644 tex/CombinatorsForCFPQ.tex delete mode 100644 tex/Conclusion.tex delete mode 100644 tex/ConjunctiveAndBooleanLanguages.tex delete mode 100644 tex/Context-Free_Languages.tex delete mode 100644 tex/DerivativesForCFPQ.tex delete mode 100644 tex/FLPQ.tex delete mode 100644 tex/FormalLanguageConstrainedReachabilityLectureNotes.bib delete mode 100644 tex/FormalLanguageConstrainedReachabilityLectureNotes.tex delete mode 100644 tex/FormalLanguageTheoryIntro.tex delete mode 100644 tex/GLL-based_CFPQ.tex delete mode 100644 tex/GLR-based_CFPQ.tex delete mode 100644 tex/GraphTheoryIntro.tex delete mode 100644 tex/Introduction.tex delete mode 100644 tex/LinearAlgebra.tex delete mode 100644 tex/List_of_contributors.tex delete mode 100644 tex/Matrix-based_CFPQ.tex delete mode 100644 tex/Multiple_Context-Free_Language_Reachability.tex delete mode 100644 tex/Multiple_Context-Free_Languages.tex delete mode 100644 tex/Project.tex delete mode 100644 tex/RPQ.tex delete mode 100644 tex/RegularLanguages.tex delete mode 100644 tex/SPPF.tex delete mode 100644 tex/TensorProduct.tex delete mode 100644 tex/figures/Chomsky.pdf delete mode 100644 tex/figures/Chomsky.svg delete mode 100644 tex/figures/GLR/CLR_example.tex delete mode 100644 tex/figures/GLR/GLR_example.tex delete mode 100644 tex/figures/GLR/LL_LR.tex delete mode 100644 tex/figures/GLR/LR0/complete.tex delete mode 100644 tex/figures/GLR/LR0/state0.tex delete mode 100644 tex/figures/GLR/LR0/state1.tex delete mode 100644 tex/figures/GLR/LR0/state2.tex delete mode 100644 tex/figures/GLR/LR0/state3.tex delete mode 100644 tex/figures/GLR/LR0/state4.tex delete mode 100644 tex/figures/GLR/LR0/state5.tex delete mode 100644 tex/figures/cfl/pumping0.tex delete mode 100644 tex/figures/cfl/pumping1.tex delete mode 100644 tex/figures/cfl/pumping2.tex delete mode 100644 tex/figures/cfl/tree0.tex delete mode 100644 tex/figures/cyk/graph1.tex delete mode 100644 tex/figures/flpq/path1.tex delete mode 100644 tex/figures/flpq/path2.tex delete mode 100644 tex/figures/gll/complete.tex delete mode 100644 tex/figures/gll/state0.tex delete mode 100644 tex/figures/gll/state1.tex delete mode 100644 tex/figures/gll/state2.tex delete mode 100644 tex/figures/gll/state3.tex delete mode 100644 tex/figures/gll/state4.tex delete mode 100644 tex/figures/gll/state5.tex delete mode 100644 tex/figures/gll/state6.tex delete mode 100644 tex/figures/gll/state7.tex delete mode 100644 tex/figures/gll/state8.tex delete mode 100644 tex/figures/graph/graph0.tex delete mode 100644 tex/figures/graph/graph1.tex delete mode 100644 tex/figures/graph/graph2.tex delete mode 100644 tex/figures/graph/graph3.tex delete mode 100644 tex/figures/graph/graph4.tex delete mode 100644 tex/figures/graph/graph5.tex delete mode 100644 tex/figures/graph/graph_BFS_1.tex delete mode 100644 tex/figures/graph/graph_BFS_2.tex delete mode 100644 tex/figures/graph/graph_BFS_3.tex delete mode 100644 tex/figures/graph/graph_MS-BFS_1.tex delete mode 100644 tex/figures/graph/graph_MS-BFS_2.tex delete mode 100644 tex/figures/graph/path0.tex delete mode 100644 tex/figures/mcfg/mcfg.pdf delete mode 100644 tex/figures/mcfg/mcfg.svg delete mode 100644 tex/figures/mcfg/mcfg_2.pdf delete mode 100644 tex/figures/mcfg/mcfg_2.svg delete mode 100644 tex/figures/multi/graph0.tex delete mode 100644 tex/figures/tensor/graph0.tex delete mode 100644 tex/figures/tensor/graph1.tex delete mode 100644 tex/figures/tensor/graph2.tex delete mode 100644 tex/figures/tensor/graph3.tex delete mode 100644 tex/figures/tensor/graph4.tex delete mode 100644 tex/figures/tensor/graph5.tex delete mode 100644 tex/figures/tensor/recursive.tex delete mode 100644 tex/makefile diff --git a/tex/CFPQ_to_Datalog.tex b/tex/CFPQ_to_Datalog.tex deleted file mode 100644 index c5c4c4a..0000000 --- a/tex/CFPQ_to_Datalog.tex +++ /dev/null @@ -1,142 +0,0 @@ -\chapter{От CFPQ к вычислению Datalog-запросов}\label{Subsection Datalog} -Рассмотрим грамматику $S \rightarrow aSb \mid SS \mid \varepsilon$, заданную через набор предикатов: -\begin{itemize} - \item $a(i, w)$ --- Предикат, соответствующий терминалу. Обращается в True, если на $i$-том месте в строке $w$ стоит символ $a$ - \item $S(i, j, w)$ --- Предикат, соответствующий нетерминалу. Обращается в True, если выполняется одно из условий: - \begin{enumerate} - \item $i == j \quad(\varepsilon)$ - \item $\exists k: i \leq k \leq j \And S(i, k - 1, w) \And S(k, j, w) \quad (SS)$ - \item ${a(i, w) \And S(i+1, j-1, w) \And b(j-1, w)} \quad (aSb)$ - \end{enumerate} -\end{itemize} - -Таким образом $S(0,|w|,w)$ покажет, выводится ли строка $w$ из данной грамматики, -а $S(\_,\_,w)$ даст нам список всех цепочек внутри $w$, выводящихся из $S$. - -\subsection{Datalog} -Datalog~\cite{Datalog}\footnote{\url{https://www.computer.org/csdl/journal/tk/1989/01/k0146/13rRUx0xPIQ}} --- декларативный логический язык программирования. Используется для написания запросов к дедуктивным базам данных\footnote{\url{https://en.wikipedia.org/wiki/Deductive_database}}. - -\begin{example} - Пример программы на даталоге. - \begin{enumerate} - \item Набор фактов (часто факты находятся в базе данных): - \begin{itemize} - \item $a(0).$ - \item $b(1).$ - \item $a(2).$ - \item $b(3).$ - \item $s(I, I).$ - \end{itemize} - \item Набор правил: - \begin{itemize} - \item $s(I, J) \coloneq s(I, K-1), s(K,J), (I \leq K \leq J)$ - \item $s(I,J)\coloneq a(I), s(I+1, J-1),b(J)$ - \end{itemize} - \item Запросы: - \begin{itemize} - \item $?- s(I, J)$ - \end{itemize} - \end{enumerate} -\end{example} - -Таким образом мы описали на даталоге строку через набор фактов, грамматику, указанную выше, через набор фактов и правил и сделали запрос на все цепочки, выводящиеся из $S$. - -\textbf{NB!} Обратите внимание~\cite{Datalog}, что строки, начинающиеся с большой буквы, в даталоге считаются переменными. Также важно, что все переменные неявно квантифицированны. - - -\subsection{Datalog для работы с графами} -На даталоге также можно задавать графы и писать к ним запросы. -\begin{example} - Пример описания графа на даталоге. - \begin{center} - \begin{tikzpicture}[shorten >=1pt,on grid,auto] - \node[state] (q_0) {$0$}; - \node[state] (q_1) [above right=of q_0] {$1$}; - \node[state] (q_2) [right=of q_0] {$2$}; - \node[state] (q_3) [right=of q_2] {$3$}; - \path[->] - (q_0) edge node {$a$} (q_1) - (q_1) edge node {$a$} (q_2) - (q_2) edge node {$a$} (q_0) - (q_2) edge[bend left, above] node {$b$} (q_3) - (q_3) edge[bend left, below] node {$b$} (q_2); - \end{tikzpicture} - \end{center} -\begin{itemize} - \item[] $a(0, 1).$ - \item[] $a(1, 2).$ - \item[] $a(2, 0).$ - \item[] $b(2, 3).$ - \item[] $b(3, 2).$ -\end{itemize} - -\end{example} - -Теперь зададим рассмотренную выше грамматику для работы с графом. -\begin{itemize} - \item[] $s(I, I).$ - \item[] $s(I,J) \coloneq s(I, K-1),s(K, J).$ - \item[] $s(I, J) \coloneq a(I, L),S(L,M),b(M,J).$ -\end{itemize} - -Тогда запрос $?-s(I, J)$ выдаст нам все такие пути в графе, что последовательность составляющих их вершин в порядке прохождения выводится их грамматики. - -\subsection{Алгоритм Эрли} -Для распознавания контекстно-свободных грамматик может использоваться алгоритм Эрли~\cite{Earley} \footnote{\url{https://en.wikipedia.org/wiki/Earley}}. -Рассмотрим грамматику $G=(N,T,P,S)$, слово $a_1...a_n$, -и правило $A \rightarrow \alpha\beta$. Будем считать, что утверждение -$[A\rightarrow \alpha \bullet \beta](i,j), j \in [1..n]$ является истиной, если верно, что: -\begin{itemize} - \item $\alpha \xrightarrow{\smash{*}} a_{i+1}...a_j$ (Последовательность выводится из $\alpha$) - \item $S \xrightarrow{\smash{*}} a_1...a_jA_\gamma$ -\end{itemize} - - -Рассмотрим правила вывода для подобных утверждений: - -\begin{enumerate} - \item $\frac{S \rightarrow \alpha \in P}{[S \rightarrow \bullet \alpha](0,0)}$ Инициализация (Init) - - \item $\frac{\left[A \rightarrow \alpha \bullet a_{j+1} \beta\right](i, j)}{\left[A \rightarrow \alpha a_{j+1} \bullet \beta\right](i, j+1)}$ Сканирование (Scan) - - \item $\frac{[A \rightarrow \alpha \cdot B \beta](i, j) \quad B \rightarrow \gamma \in P}{[B \rightarrow \bullet \gamma](j, j)}$ Предсказание (Predict) - - \item $\frac{[A \rightarrow \alpha \cdot B](i, j) \quad[B \rightarrow \gamma \bullet](j, k)}{[A \rightarrow \alpha B \bullet \beta](i, k)}$ Завершение (Complete) - -\end{enumerate} - -Идея алгоритма Эрли заключается в том, чтобы, начиная с инициализации, используя правила, вывести утверждение, содержащие данную строку слева от точки, и ничего справа, или попробовать все возможные выводы и признать, что строка не выводима. - -Сложность алгоритма Эрли составляет $O(|P|^2n^3)$ - -\begin{example} Пример начала одной из веток дерева вывода для алгоритма Эрли для рассматриваемой грамматики - - $$\underline{S \rightarrow SS} \quad Init$$ - $$\underline{[S \rightarrow \bullet SS](0,0), \space S \rightarrow aSb} \quad Predict$$ - $$\underline{[S \rightarrow \bullet aSb](0,0)} \quad Scan$$ - $$\underline{[S \rightarrow a \bullet Sb](0,1), S \rightarrow \varepsilon} \quad Predict$$ - $$\underline{[S \rightarrow \bullet](0, 1), [S \rightarrow aS \bullet b](0,1)} \quad Complete$$ - $$\underline{[S \rightarrow aS \bullet b](0,1)} \quad Scan$$ - $$\underline{[S \rightarrow \bullet SS](0,0),[S \rightarrow aSb \bullet](0,2)} \quad Complete$$ - $$[\underline{S \rightarrow S \bullet S](0,2)}$$ - $$\cdot\cdot\cdot$$ - -\end{example} - -Сложность можно понизить, изменив правила ``Предсказание'' и ``Завершение'' таким образом: -\begin{itemize} - \item $\frac{[A \rightarrow \alpha \cdot B \beta](i, j) \quad B \rightarrow \gamma \in P}{[B \rightarrow \bullet \gamma](j, j)} \Rightarrow$ $ - \frac{[A \rightarrow \alpha \cdot B \beta](i, j)}{? B(j)}; \quad \frac{? B(j) \quad B \rightarrow \gamma \in P}{[B \rightarrow \cdot \gamma](j, j)}$ - \item $\frac{[A \rightarrow \alpha \cdot B](i, j) \quad[B \rightarrow \gamma \bullet](j, k)}{[A \rightarrow \alpha B \bullet \beta](i, k)} \Rightarrow$ $\frac{[B \rightarrow \gamma \bullet](j, k)}{B(j, k)}; \quad \frac{[A \rightarrow \alpha \cdot B \beta](i, j) \quad B(j, k)}{[A \rightarrow \alpha B \cdot \beta](i, k)}$ -\end{itemize} -Так, разложив каждое правило на два, мы избавляемся от необходимости перевычислять дерево разбора каждого нетерминала после того, как однократно вычислим, что он выводим (мемоизируем его). Получаем сложность $O(|P|)$. - -Описанный подход мемоизации~\cite{Magic} части используется для оптимизации программ на даталоге. Можно либо видоизменять правила, задающие грамматику в тексте программы, либо модифицировать компилятор, чтобы он пытался сделать это автоматически. -\section{Вопросы и задачи} -\begin{enumerate} - \item Написать синтаксический анализатор раз. - \item Написать синтаксический анализатор два. - \item Побаловаться с неоднозначными грамматиками - \item Побаловаться с конъюнктивными грамматиками. - \item Графы? -\end{enumerate} \ No newline at end of file diff --git a/tex/CYK_for_CFPQ.tex b/tex/CYK_for_CFPQ.tex deleted file mode 100644 index 5742ef6..0000000 --- a/tex/CYK_for_CFPQ.tex +++ /dev/null @@ -1,732 +0,0 @@ -\chapter{CYK для вычисления КС запросов}\label{chpt:CFPQ_CYK} - -В данной главе мы рассмотрим алгоритм CYK, позволяющий установить принадлежность слова грамматике и предоставить его вывод, если таковой имеется. - -Наш главный интерес заключается в возможности применения данного алгоритма для решения описанной в предыдущей главе задачи --- поиска путей с ограничениями в терминах формальных языков. Как уже было указано выше, будем рассматривать случай контекстно-свободных языков. - -\section{Алгоритм CYK}\label{sect:lin_CYK} - -Алгоритм CYK (Cocke-Younger-Kasami) --- один из классических алгоритмов синтаксического анализа. Его асимптотическая сложность в худшем случае --- $O(n^3 * |N|)$, где $n$ --- длина входной строки, а $N$ --- количество нетерминалов во входной грамматике~\cite{Hopcroft+Ullman/79/Introduction}. - -Для его применения необходимо, чтобы подаваемая на вход грамматика находилась в Нормальной Форме Хомского (НФХ)~\ref{section:CNF}. Других ограничений нет и, следовательно, данный алгоритм применим для работы с произвольными контекстно-своболными языками. - -В основе алгоритма лежит принцип динамического программирования. Используются два соображения: - -\begin{enumerate} -\item Из нетерминала $A$ выводится цепочка $\omega$ при помощи правила $A \to a$ тогда и только тогда, когда $a= \omega$: -\[ - A \derives \omega \iff \omega = a -\] - -\item Из нетерминала $A$ выводится цепочка $\omega$ при помощи правила $A \to B C$ тогда и только тогда, когда существуют две цепочки $\omega_1$ и $\omega_2$ такие, что $\omega_1$ выводима из $B$, $\omega_2$ выводима из $C$ и при этом $\omega = \omega_1 \omega_2$: -\[ -A \derives[] B C \derives \omega \iff \exists \omega_1, \omega_2 : \omega = \omega_1 \omega_2, B \derives \omega_1, C \derives \omega_2 -\] - -Переформулируем эти утверждения в терминах позиций в строке: -\[ -A \derives[] B C \derives \omega \iff \exists k \in [1 \dots |\omega|] : B \derives \omega[1 \dots k], C \derives \omega[k+1 \dots |\omega|] -\] -\end{enumerate} - -В процессе работы алгоритма заполняется булева трехмерная матрица $M$ размера $n \times n \times |N|$ таким образом, что -\[M[i, j, A] = true \iff A \derives \omega[i \dots j]\]. - -Первым шагом инициализируем матрицу, заполнив значения $M[i, i, A]$: - -\begin{itemize} - \item $M[i, i, A] = true \text{, если в грамматике есть правило } A \to \omega[i]$. - \item $M[i, i, A] = false$, иначе. -\end{itemize} - -Далее используем динамику: на шаге $m > 1$ предполагаем, что ячейки матрицы $M[i', j', A]$ заполнены для всех нетерминалов $A$ и пар $i', j': j' - i' < m$. -Тогда можно заполнить ячейки матрицы $M[i, j, A] \text{, где } j - i = m$ следующим образом: -\[ M[i, j, A] = \bigvee_{A \to B C}^{}{\bigvee_{k=i}^{j-1}{M[i, k, B] \wedge M[k, j, C]}} \] - -По итогу работы алгоритма значение в ячейке $M[0, |\omega|, S]$, где $S$ --- стартовый нетерминал грамматики, отвечает на вопрос о выводимости цепочки $\omega$ в грамматике. - -\begin{example}\label{exampl:CYK} - Рассмотрим пример работы алгоритма CYK на грамматике правильных скобочных последовательностей в Нормальной Форме Хомского. - - -\begin{align*} -S &\to A S_2 \mid \varepsilon & S_2 &\to b \mid B S_1 \mid S_1 S_3 & A &\to a \\ -S_1 &\to A S_2 & S_3 &\to b \mid B S_1 & B &\to b\\ -\end{align*} - -Проверим выводимость цепочки $\omega = a a b b a b$. - -Так как трехмерные матрицы рисовать на двумерной бумаге не очень удобно, мы будем иллюстрировать работу алгоритма двумерными матрицами размера $n \times n$, где в ячейках указано множество нетерминалов, выводящих соответствующую подстроку. - -Шаг 1. Инициализируем матрицу элементами на главной диагонали: - -\[ -\begin{pmatrix} -\{A\} & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ -\varnothing & \{A\} & \varnothing & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \varnothing \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ -\end{pmatrix} -\] - -Шаг 2. Заполняем диагональ, находящуюся над главной: - -\[ -\begin{pmatrix} -\{A\} & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ -\varnothing & \{A\} & \cellcolor{lightgray}\{S_1\} & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \cellcolor{lightgray}\{S_1\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ -\end{pmatrix} -\] - -В двух ячейках появилисб нетерминалы $S_1$ благодяря присутствиб в грамматике правила $S_1 \to A S_2$. - -Шаг 3. Заполняем следующую диагональ: - -\[ -\begin{pmatrix} -\{A\} & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ -\varnothing & \{A\} & \{S_1\} & \cellcolor{lightgray}\{S_2\} & \varnothing & \varnothing \\ -\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \cellcolor{lightgray}\{S_2, S_3\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \{S_1\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ -\end{pmatrix} -\] - -Шаг 4. И следующую за ней: - -\[ -\begin{pmatrix} -\{A\} & \varnothing & \varnothing & \cellcolor{lightgray}\{S_1, S\} & \varnothing & \varnothing \\ -\varnothing & \{A\} & \{S_1\} & \{S_2\} & \varnothing & \varnothing \\ -\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \{S_2, S_3\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \{S_1\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ -\end{pmatrix} -\] - -Шаг 5 Заполняем предпоследнюю диагональ: - -\[ -\begin{pmatrix} -\{A\} & \varnothing & \varnothing & \{S_1, S\} & \varnothing & \varnothing \\ -\varnothing & \{A\} & \{S_1\} & \{S_2\} & \varnothing & \cellcolor{lightgray}\{S_2\} \\ -\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \{S_2, S_3\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \{S_1\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ -\end{pmatrix} -\] - -\bigbreak -Шаг 6. Завершаем выполнение алгоритма: - -\[ -\begin{pmatrix} -\{A\} & \varnothing & \varnothing & \{S_1, S\} & \varnothing & \cellcolor{lightgray}\{S_1, S\} \\ -\varnothing & \{A\} & \{S_1\} & \{S_2\} & \varnothing & \{S_2\} \\ -\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \{S_2, S_3\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \{S_1\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ -\end{pmatrix} -\] - - -Стартовый нетерминал находится в верхней правой ячейке, а значит цепочка $a a b b a b$ выводима в нашей грамматике. -\end{example} - -\begin{example} -Теперь выполним алгоритм на цепочке $\omega=abaa$. - -Шаг 1. Инициализируем таблицу: - -\[ -\begin{pmatrix} -\{A\} & \varnothing & \varnothing & \varnothing \\ -\varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing \\ -\varnothing & \varnothing & \{A\} & \varnothing \\ -\varnothing & \varnothing & \varnothing & \{A\} \\ -\end{pmatrix} -\] - -Шаг 2. Заполняем следующую диагональ: - -\[ -\begin{pmatrix} -\{A\} & \cellcolor{lightgray}\{S_1, S\} & \varnothing & \varnothing \\ -\varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing \\ -\varnothing & \varnothing & \{A\} & \varnothing \\ -\varnothing & \varnothing & \varnothing & \{A\} \\ -\end{pmatrix} -\] - -Больше ни одну ячейку в таблице заполнить нельзя и при этом стартовый нетерминал отсутствует в правой верхней ячейке, а значит эта строка не выводится в грамматике правильных скобочных последовательностей. - -\end{example} - -\section{Алгоритм для графов на основе CYK} -\label{graph:CYK} -Первым шагом на пути к решению задачи достижимости с использованием CYK является модификация представления входа. Прежде мы сопоставляли каждому символу слова его позицию во входной цепочке, поэтому при инициализации заполняли главную диагональ матрицы. Теперь вместо этого обозначим числами позиции между символами. В результате слово можно представить в виде линейного графа следующим образом(в качестве примера рассмотрим слово $a a b b a b$ из предыдущей главы~\ref{sect:lin_CYK}): - -\begin{center} - \begin{tikzpicture}[shorten >=1pt,on grid,auto] - \node[state] (q_0) at (0,0) {$0$}; - \node[state] (q_1) at (2,0) {$1$}; - \node[state] (q_2) at (4,0) {$2$}; - \node[state] (q_3) at (6,0) {$3$}; - \node[state] (q_4) at (8,0) {$4$}; - \node[state] (q_5) at (10,0) {$5$}; - \node[state] (q_6) at (12,0) {$6$}; - \path[->] - (q_0) edge node {$a$} (q_1) - (q_1) edge node {$a$} (q_2) - (q_2) edge node {$b$} (q_3) - (q_3) edge node {$b$} (q_4) - (q_4) edge node {$a$} (q_5) - (q_5) edge node {$b$} (q_6); - \end{tikzpicture} -\end{center} - -Что нужно изменить в описании алгоритма, чтобы он продолжал работать при подобной нумерации? Каждая буква теперь идентифицируется не одним числом, а парой --- номера слева и справа от нее. При этом чисел стало на одно больше, чем при прежнем способе нумерации. - -Возьмем матрицу $(n + 1) \times (n + 1) \times |N|$ и при инициализации будем заполнять не главную диагональ, а диагональ прямо над ней. Таким образом, мы начинаем наш алгоритм с определения значений $M[i, j, A] \text{, где } j = i + 1$. При этом наши дальнейшие действия в рамках алгоритма не изменятся. - -Для примера~\ref{exampl:CYK} на шаге инициализации матрица выглядит следующим образом: - -\[ -\begin{pmatrix} -\varnothing & \{A\} & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \{A\} & \varnothing & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \varnothing \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ - -\end{pmatrix} -\] - -А в результате работы алгоритма имеем: - -\[ -\begin{pmatrix} -\varnothing & \{A\} & \varnothing & \varnothing & \{S_1, S\} & \varnothing & \{S_1, S\} \\ -\varnothing & \varnothing & \{A\} & \{S_1\} & \{S_2\} & \varnothing & \{S_2\} \\ -\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ -\varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \{S_2, S_3\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \{S_1\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ -\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} -\] - -Мы представили входную строку в виде линейного графа, а на шаге инициализации получили его матрицу смежности. Добавление нового нетерминала в язейку матрицы можно рассматривать как нахождение нового пути между соответствующими вершинами, выводимого из добавленного нетерминала. Таким образом, шаги алгоритма напоминают построение транзитивного замыкания графа. Различие заключается в том, что мы добавляем новые ребра только для тех пар нетерминалов, для которых существует соответстующее правило в грамматике. - -Алгоритм можно обобщить и на произвольные графы с метками, рассматриваемые в этом курсе. При этом можно ослабить ограничение на форму входной грамматики: она должна находиться в ослабленной Нормальной Форме Хомского~(\ref{defn:wCNF}). - -Шаг инициализации в алгоритме теперь состоит из двух пунктов. -\begin{itemize} -\item Как и раньше, с помощью продукций вида \[A \to a \text{, где } A \in N, a \in \Sigma\] -заменяем терминалы на ребрах входного графа на множества нетерминалов, из которых они выводятся. -\item Добавляем в каждую вершину петлю, помеченную множеством нетерминалов для которых в данной грамматике есть правила вида $$A \to \varepsilon\text{, где } A \in N.$$ -\end{itemize} - - Затем используем матрицу смежности получившегося графа (обозначим ее $M$) в качестве начального значения. Дальнейший ход алгоритма можно описать псевдокодом, представленным в листинге~\ref{alg:graphParseCYK}. - -\begin{algorithm}[H] - \begin{algorithmic}[1] - \caption{Алгоритм КС достижимости на основе CYK} - \label{alg:graphParseCYK} - \Function{contextFreePathQuerying}{G, $\mathcal{G}$} - - \State{$n \gets$ the number of nodes in $\mathcal{G}$} - \State{$M \gets$ the modified adjacency matrix of $\mathcal{G}$} - \State{$P \gets$ the set of production rules in $G$} - \While{$M$ is changing} - \For {$k \in 0..n$} - \For {$i \in 0..n$} - \For {$j \in 0..n$} - \ForAll {$N_1 \in M[i, k]$, $N_2 \in M[k, j]$} - \If {$N_3 \to N_1 N_2 \in P$ } - \State{$M[i, j] \mathrel{+}= \{N_3\}$} - \EndIf - \EndFor - \EndFor - \EndFor - \EndFor - \EndWhile - \State \Return $M$ - \EndFunction - \end{algorithmic} -\end{algorithm} - -После завершения алгоритма, если в некоторой ячейке результируюшей матрицы с номером $(i, j)$ находятся стартовый нетерминал, то это означает, что существует путь из вершины $i$ в вершину $j$, удовлетворяющий данной грамматике. Таким образом, полученная матрица является ответом для задачи достижимости для заданных графа и грамматики. - -\begin{example} -\label{CYK_algorithm_ex} -Рассмотрим работу алгоритма на графе - -\begin{center} - \input{figures/graph/graph0.tex} -\end{center} - -и грамматике: - -\begin{align*} -S & \to A B & A & \to a \\ -S & \to A S_1 & B & \to b\\ -S_1 & \to S B &&\\ -\end{align*} - -Данный пример является классическим и еще не раз будет использоваться в рамках данного курса. \\ - -\textbf{Инициализация.} -Заменяем терминалы на ребрах графа на нетерминалы, из которых они выводятся, и строим матрицу смежности получившегося графа: - -\begin{center} - \input{figures/cyk/graph1.tex} -\end{center} - -\[ -\begin{pmatrix} -\varnothing & \{A\} & \varnothing & \varnothing \\ -\varnothing & \varnothing & \{A\} & \varnothing \\ -\{A\} & \varnothing & \varnothing & \{B\} \\ -\varnothing & \varnothing & \{B\} & \varnothing \\ -\end{pmatrix} -\] - -\textbf{Итерация 1.} -Итерируемся по $k$, $i$ и $j$, пытаясь найти пары нетерминалов, для которых существуют правила вывода, их выводящие. Нам интересны следующие случаи: - -\begin{itemize} - \item $k = 2, i = 1, j = 3: A \in M[1, 2], B \in M[2, 3]$, так как в грамматике присутствует правило $S \to A B$, добавляем нетерминал $S$ в ячейку $M[1, 3]$. - \item $k = 3, i = 1, j = 2: S \in M[1, 3], B \in M[3, 2]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[1, 2]$. -\end{itemize} - -В остальных случаях либо какая-то из клеток пуста, либо не существует продукции в грамматике, выводящей данные два нетерминала. - -Матрица после данной итерации: - -\[ -\begin{pmatrix} -\varnothing & \{A\} & \varnothing & \varnothing \\ -\varnothing & \varnothing & \cellcolor{lightgray}\{A, \boldsymbol{S_1}\} & \cellcolor{lightgray}\{S\} \\ -\{A\} & \varnothing & \varnothing & \{B\} \\ -\varnothing & \varnothing & \{B\} & \varnothing \\ -\end{pmatrix} -\] - -\textbf{Итерация 2.} -Снова итерируемся по $k$, $i$, $j$. Рассмотрим случаи: - -\begin{itemize} - \setlength\itemsep{1em} - \item $k = 1, i = 0, j = 2: A \in M[0, 1], S_1 \in M[1, 2]$, так как в грамматике присутствует правило $S \to A S_1$, добавляем нетерминал $S$ в ячейку $M[0, 2]$. - \item $k = 2, i = 0, j = 3: S \in M[0, 2], B \in M[2, 3]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[0, 3]$. -\end{itemize} - -Матрица на данном шаге: - -\[ -\begin{pmatrix} -\varnothing & \{A\} & \cellcolor{lightgray}\{S\} & \cellcolor{lightgray}\{S_1\} \\ -\varnothing & \varnothing & \{A, S_1\} & \{S\} \\ -\{A\} & \varnothing & \varnothing & \{B\} \\ -\varnothing & \varnothing & \{B\} & \varnothing \\ -\end{pmatrix} -\] - -\textbf{Итерация 3.} -Рассматриваемые на данном шаге случаи: - -\begin{itemize} - \setlength\itemsep{1em} - \item $k = 0, i = 2, j = 3: A \in M[2, 0], S_1 \in M[0, 3]$, так как в грамматике присутствует правило $S \to A S_1$, добавляем нетерминал $S$ в ячейку $M[2, 3]$. - \item $k = 3, i = 2, j = 2: S \in M[2, 3], B \in M[3, 2]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[2, 2]$. -\end{itemize} - -Матрица после этой итерации: - -\[ -\begin{pmatrix} -\varnothing & \{A\} & \{S\} & \{S_1\} \\ -\varnothing & \varnothing & \{A, S_1\} & \{S\} \\ -\{A\} & \varnothing & \cellcolor{lightgray}\{S_1\} & \cellcolor{lightgray}\{B, \boldsymbol{S}\} \\ -\varnothing & \varnothing & \{B\} & \varnothing \\ -\end{pmatrix} -\] - -\textbf{Итерация 4.} -Рассмариваемые случаи: - -\begin{itemize} - \setlength\itemsep{1em} - \item $k = 2, i = 1, j = 2: A \in M[1, 2], S_1 \in M[2, 2]$, так как в грамматике присутствует правило $S \to A S_1$, добавляем нетерминал $S$ в ячейку $M[1, 2]$. - \item $k = 2, i = 1, j = 3: S \in M[1, 2], B \in M[2, 3]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[1, 3]$. -\end{itemize} - -Матрица: - -\[ -\begin{pmatrix} -\varnothing & \{A\} & \{S\} & \{S_1\} \\ -\varnothing & \varnothing & \cellcolor{lightgray}\{A, \boldsymbol{S}, S_1\} & \cellcolor{lightgray}\{S, \boldsymbol{S_1}\} \\ -\{A\} & \varnothing & \{S_1\} & \{B, S\} \\ -\varnothing & \varnothing & \{B\} & \varnothing \\ -\end{pmatrix} -\] - -\textbf{Итерация 5.} -Рассмотрим на это шаге: - -\begin{itemize} - \setlength\itemsep{1em} - \item $k = 1, i = 0, j = 3: A \in M[0, 1], S_1 \in M[1, 3]$, поскольку в грамматике есть правило $S \to A S_1$, добавляем нетерминал $S$ в ячейку $M[0, 3]$. - \item $k = 3, i = 0, j = 2: S \in M[0, 3], B \in M[3, 2]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[0, 2]$. -\end{itemize} - -Матрица на этой итерации: -\[ -\begin{pmatrix} -\varnothing & \{A\} & \cellcolor{lightgray}\{S, \boldsymbol{S_1}\} & \cellcolor{lightgray}\{\boldsymbol{S}, S_1\} \\ -\varnothing & \varnothing & \{A, S, S_1\} & \{S, S_1\} \\ -\{A\} & \varnothing & \{S_1\} & \{B, S\} \\ -\varnothing & \varnothing & \{B\} & \varnothing \\ -\end{pmatrix} -\] - -\textbf{Итерация 6.} -Интересующие нас на этом шаге случаи: - -\begin{itemize} - \setlength\itemsep{1em} - \item $k = 0, i = 2, j = 2: A \in M[2, 0], S_1 \in M[0, 2]$, поскольку в грамматике есть правило $S \to A S_1$, добавляем нетерминал $S$ в ячейку $M[2, 2]$. - \item $k = 2, i = 2, j = 3: S \in M[2, 2], B \in M[2, 3]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[2, 3]$. -\end{itemize} - -Матрица после данного шага: - -\[ -\begin{pmatrix} -\varnothing & \{A\} & \{S, S_1\} & \{S, S_1\} \\ -\varnothing & \varnothing & \{A, S, S_1\} & \{S, S_1\} \\ -\{A\} & \varnothing & \cellcolor{lightgray}\{\boldsymbol{S}, S_1\} & \cellcolor{lightgray}\{B, S, \boldsymbol{S_1}\} \\ -\varnothing & \varnothing & \{B\} & \varnothing \\ -\end{pmatrix} -\] - -На следующей итерации матрица не изменяется, поэтому заканчиваем работу алгоритма. В результате, если ячейка $M[i, j]$ содержит стартовый нетерминал $S$, то существует путь из $i$ в $j$, удовлетворяющий ограничениям, заданным грамматикой. -\end{example} - -Можно заметить, что мы делаем много лишних итераций. -Можно переписать алгоритм так, чтобы он не просматривал заведомо пустые ячейки. -Данную модификацию предложил Й.Хеллингс в работе~\cite{hellingsRelational}, также она реализована в работе~\cite{10.1007/978-3-319-46523-4_38}. - -Псевдокод алгоритма Хеллингса представлен в листинге~\ref{alg:graphParseHellings}. - -\begin{algorithm}[H] - \begin{algorithmic}[1] - \caption{Алгоритм Хеллингса} - \label{alg:graphParseHellings} - \Function{contextFreePathQuerying}{$G= \langle \Sigma, N, P, S \rangle$, $\mathcal{G} = \langle V,E,L \rangle$} - - \State{$r \gets \{(N_i,v,v) \mid v \in V \wedge N_i \to \varepsilon \in P \} \cup \{(N_i,v,u) \mid (v,t,u) \in E \wedge N_i \to t \in P \}$} - \State{$m \gets r$} - \While{$m \neq \varnothing$} - \State{$(N_i,v,u) \gets$ m.pick()} - \For {$(N_j,v',v) \in r$} - \For {$N_k \to N_j N_i \in P$ таких что $((N_k, v',u) \notin r)$} - \State{$m \gets m \cup \{(N_k, v',u)\}$} - \State{$r \gets r \cup \{(N_k, v',u)\}$} - \EndFor - \EndFor - \For {$(N_j,u,v') \in r$} - \For {$N_k \to N_i N_j \in P$ таких что $((N_k, v, v') \notin r)$} - \State{$m \gets m \cup \{(N_k, v, v')\}$} - \State{$r \gets r \cup \{(N_k, v, v')\}$} - \EndFor - \EndFor - - \EndWhile - \State \Return $r$ - \EndFunction - \end{algorithmic} -\end{algorithm} - - -\begin{example} - Запустим алгоритм Хеллингса на нашем примере. - - \textbf{Инициализация} - $$ - m = r = \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2)\} - $$ - - \textbf{Итерации внешнего цикла.} Будем считеть, что $r$ и $m$ --- упорядоченные списки и $pick$ возвращает его голову, оставляя хвост. - Новые элементы добавляются в конец. - \begin{enumerate} - \item Обрабатываем $(A,0,1)$. - Ни один из вложенных циклов не найдёт новых путей, так как для рассматриваемого ребра есть только две возможности достроить путь: $2 \xrightarrow{A} 0 \xrightarrow{A} 1$ и $0 \xrightarrow{A} 1 \xrightarrow{A} 2$ - и ни одна из соответствующих строк не выводтся в заданной грамматике. - \item Перед началом итерации - $$ - m = \{(A,1,2),(A,2,0),(B,2,3),(B,3,2)\}, - $$ $r$ не изменилось. - Обрабатываем $(A,1,2)$. - В данной ситуации второй цикл найдёт тройку $(B,2,3)$ и соответсвующее правило $S \to A \ B$. - Это значит, что и в $m$ и в $r$ добавится тройка $(S, 1, 3)$. - \item - Перед началом итерации - $$ - m = \{(A,2,0),(B,2,3),(B,3,2),(S,1,3)\}, - $$ - $$ - r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3)\}. - $$ - Обрабатываем $(A,2,0)$. - Внутринние циклы ничего не найдут, новых путей н появится. - \item - Перед началом итерации - $$ - m = \{(B,2,3),(B,3,2),(S,1,3)\}, - $$ - $$ - r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3)\}. - $$ - Обрабатываем $(B,2,3)$. - Первый цикл мог бы найти $(A,1,2)$, однако при проверке во вложенном цикле выяснится, что $(S, 1, 3)$ уже найдена. - В итоге, на данной итерации новых путей н появится. - \item - Перед началом итерации - $$ - m = \{(B,3,2),(S,1,3)\}, - $$ - $$ - r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3)\}. - $$ - Обрабатываем $(B,3,2)$. - Первый цикл найдёт $(S,1,3)$ и соответствующее правило $S_1 \to S \ B$. - Это значит, что и в $m$ и в $r$ добавится тройка $(S_1, 1, 2)$. - \item - Перед началом итерации - $$ - m = \{(S,1,3),(S_1, 1, 2)\}, - $$ - $$ - r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2)\}. - $$ - Обрабатываем $(S,1,3)$. - Второй цикл мог бы найти $(B,3,2)$, однако при проверке во вложенном цикле выяснится, что $(S_1, 1, 2)$ уже найдена. - В итоге, на данной итерации новых путей н появится. - \item - Перед началом итерации - $$ - m = \{(S_1, 1, 2)\}, - $$ - $$ - r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2)\}. - $$ - Обрабатываем $(S_1,1,2)$. - Первый цикл найдёт $(A,0,1)$ и соответствующее правило $S \to A \ S_1$. - Это значит, что и в $m$ и в $r$ добавится тройка $(S, 0, 2)$. - - \item - Перед началом итерации - $$ - m = \{(S, 0, 2)\}, - $$ - $$ - r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2)\}. - $$ - Обрабатываем $(S, 0, 2)$. - Найдено: $(B,2,3)$ и соответствующее правило $S_1 \to S \ B$. - B $m$ и в $r$ добавится тройка $(S_1, 0, 3)$. - - \item - Перед началом итерации - $$ - m = \{(S_1, 0, 3)\}, - $$ - \begin{align*} - r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ - &(S_1, 0, 3)\}. - \end{align*} - Обрабатываем $(S_1, 0, 3)$. - Найдено: $(A,2,0)$ и соответствующее правило $S \to A \ S_1$. - B $m$ и в $r$ добавится тройка $(S, 2, 3)$. - - \item - Перед началом итерации - $$ - m = \{(S, 2, 3)\}, - $$ - \begin{align*} - r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ - &(S_1, 0, 3),(S, 2, 3)\}. - \end{align*} - - Обрабатываем $(S, 2, 3)$. - Найдено: $(B,3,2)$ и соответствующее правило $S_1 \to S \ B$. - B $m$ и в $r$ добавится тройка $(S_1, 2, 2)$. - - \item - Перед началом итерации - $$ - m = \{(S_1, 2, 2)\}, - $$ - \begin{align*} - r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ - &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2)\}. - \end{align*} - Обрабатываем $(S_1, 2, 2)$. - Найдено: $(A,1,2)$ и соответствующее правило $S \to A \ S_1$. - B $m$ и в $r$ добавится тройка $(S, 1, 2)$. - - \item - Перед началом итерации - $$ - m = \{(S, 1, 2)\}, - $$ - \begin{align*} - r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ - &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2)\}. - \end{align*} - Обрабатываем $(S, 1, 2)$. - Найдено: $(B,2,3)$ и соответствующее правило $S_1 \to S \ B$. - B $m$ и в $r$ добавится тройка $(S_1, 1, 3)$. - - \item - Перед началом итерации - $$ - m = \{(S_1, 1, 3)\}, - $$ - \begin{align*} - r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ - &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2),(S_1, 1, 3)\}. - \end{align*} - Обрабатываем $(S_1, 1, 3)$. - Найдено: $(A,0,1)$ и соответствующее правило $S \to A \ S_1$. - B $m$ и в $r$ добавится тройка $(S, 0, 3)$. - - \item - Перед началом итерации - $$ - m = \{(S, 0, 3)\}, - $$ - \begin{align*} - r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ - &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2),(S_1, 1, 3),(S, 0, 3)\}. - \end{align*} - Обрабатываем $(S, 0, 3)$. - Найдено: $(B,3,2)$ и соответствующее правило $S_1 \to S \ B$. - B $m$ и в $r$ добавится тройка $(S_1, 0, 2)$. - - \item - Перед началом итерации - $$ - m = \{(S_1, 0, 2)\}, - $$ - \begin{align*} - r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ - &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2),(S_1, 1, 3),(S, 0, 3),(S_1, 0, 2)\}. - \end{align*} - Обрабатываем $(S_1, 0, 2)$. - Найдено: $(A,2,0)$ и соответствующее правило $S \to A \ S_1$. - B $m$ и в $r$ добавится тройка $(S, 2, 2)$. - - \item - Перед началом итерации - $$ - m = \{(S, 2, 2)\}, - $$ - \begin{align*} - r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ - &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2),(S_1, 1, 3),(S, 0, 3),(S_1, 0, 2),\\ - &(S, 2, 2)\}. - \end{align*} - Обрабатываем $(S, 2, 2)$. - Найдено: $(B,2,3)$ и соответствующее правило $S_1 \to S \ B$. - B $m$ и в $r$ добавится тройка $(S_1, 2, 3)$. - - \item - Перед началом итерации - $$ - m = \{(S_1, 2, 3)\}, - $$ - \begin{align*} - r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ - &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2),(S_1, 1, 3),(S, 0, 3),(S_1, 0, 2),\\ - &(S, 2, 2),(S_1, 2, 3)\}. - \end{align*} - Обрабатываем $(S_1, 2, 3)$. - Могло бы быть найдено: $(A,1,2)$ и соответствующее правило $S \to A \ S_1$, однако тройка $(S, 1, 3)$ уже есть в $r$. - А значит никаких новых троек найдено не будет и $m$ становится пустым. - Это была последняя итерация внешнего цикла, в $r$ на текущий момент уже содержится всё ршение. - - \end{enumerate} - -\end{example} - -Как можно заметить, количество итераций внешнего цикла также получилось достаточно большим. -Проверьте, зависит ли оно от порядка обработки элементов из $m$. -При этом внутренние циклы в нашем случае достаточно короткие, так как просматриваются только ``существенные'' элементы и избегается дублирование. - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item Проверить работу алгоритма CYK для цепочек на грамматике -% \begin{flushleft} -% $E \to E + E$ \\ -% $E \to E * E$ \\ -% $E \to (E)$ \\ -% $E \to n$ \\ -% \end{flushleft} -% и словах (алфавит $\Sigma = \{n, +, *, (, )\}$) -% \begin{flushleft} -% $ (n + n) * n$ \\ -% $ n + n * n$ \\ -% $n + n + n + n$ \\ -% $n + (n * n) + n$ \\ -% \end{flushleft} -% -% \item Изучить вычислительную сложность алгоритма CYK для матриц в зависимости от размера входного графа (размер грамматики считать фиксированным). -% -% \item Проверить работу алгоритма CYK для графов на графе -% -% \begin{center} -% \begin{tikzpicture}[node distance=3cm,shorten >=1pt,on grid,auto] -% \node[state] (q_0) {$0$}; -% \node[state] (q_1) [right=of q_0] {$1$}; -% \node[state] (q_2) [right=of q_1] {$2$}; -% \node[state] (q_3) [right=of q_2] {$3$}; -% \node[state] (q_4) [right=of q_3] {$4$}; -% \path[->] -% (q_0) edge node {$a$} (q_1) -% (q_1) edge node {$b$} (q_2) -% (q_2) edge node {$a$} (q_3) -% (q_3) edge node {$b$} (q_4) -% (q_1) edge[bend left, above] node {$b$} (q_3) -% (q_4) edge[bend left, below] node {$a$} (q_1); -% \end{tikzpicture} -% \end{center} -% -% И грамматике -% -% \begin{flushleft} -% $S \to S S$ \\ -% $S \to A B$ \\ -% $A \to a$ \\ -% $B \to b$ \\ -% \end{flushleft} -% -% \item Оцените временную сложность алгоритма Хеллингса и сравните её с оценкой для наивного обобщения CYK. -% -%\end{enumerate} diff --git a/tex/CombinatorsForCFPQ.tex b/tex/CombinatorsForCFPQ.tex deleted file mode 100644 index ebf64e3..0000000 --- a/tex/CombinatorsForCFPQ.tex +++ /dev/null @@ -1,28 +0,0 @@ -\chapter{Комбинаторы для КС запросов} - -\section{Парсер комбинаторы} - -Что это, с чем едят, плюсы, минусы. Про семантику, безопасность, левую рекурсию и т.д. -Набор примитивных парсеров и функций, которые умеют из существующих арсеров строить более сложные (собственно, комбинаторы парсеров). - -Разобрать символ, разобрать последовательность, разобрать альтернативу. впринципе, этого достаточно, но это не очень удобно. - -Проблемы с левой рекурсией. -Существуют решения. Одно из них --- Meerkat. -Подробно про него? - -\section{Комбинаторы для КС запросов} - -Вообще говоря, идея использовать комбинаторы для навигации по графам достаточно очевидно и не нова. -немного про Trails~\cite{Kroni:2013:PGA:2489837.2489844}. - -Комбинаторы для запросов к графам на основе Meerkat~\cite{Verbitskaia:2018:PCC:3241653.3241655} - -Обобщённые запросы, типобезопасность и всё такое. -Примеры запросов. - -\section{Вопросы и задачи} -\begin{enumerate} - \item Реализовать библиотеку парсер комбинаторов. - \item Что-нибудь полезное с ними сделать. -\end{enumerate} diff --git a/tex/Conclusion.tex b/tex/Conclusion.tex deleted file mode 100644 index 1a7eb25..0000000 --- a/tex/Conclusion.tex +++ /dev/null @@ -1,7 +0,0 @@ -\chapter{Заключение} - -Общие заключительные слова - -Про работы и частные случаи в статическом анализе, теоретическая сложность~\cite{10.1145/3571252, istomina2023finegrained}, свежие результаты и обзоры~\cite{10.1145/3583660.3583664}. - -Про то, что ещё интересного происходит в этой области, куда можно двигаться, ссылки на ключевые работы. diff --git a/tex/ConjunctiveAndBooleanLanguages.tex b/tex/ConjunctiveAndBooleanLanguages.tex deleted file mode 100644 index 2c8a84e..0000000 --- a/tex/ConjunctiveAndBooleanLanguages.tex +++ /dev/null @@ -1,235 +0,0 @@ -\chapter{Конъюнктивные и булевы грамматики} - -Впервые конъюнктивные и булевы грамматики были предложены Александром Охотиным~\cite{DBLP:journals/jalc/Okhotin01,Okhotin:2003:BG:1758089.1758123}. Дадим определение конъюнктивной грамматики. - -\begin{definition} - \textit{Конъюнктивной грамматикой} называется $G = (\Sigma,N,P,S)$, где: - \begin{itemize} - \item $\Sigma$ и $N$ --- дизъюнктивные конечные непустые множества терминалов и нетерминалов. - \item $P$ --- конечное множество продукций, каждая вида - \[ - A\rightarrow \alpha_1\&...\&\alpha_n - \] - ,где $A \in N,n \geq 1$ и $\alpha_1,...,\alpha_n \in (\Sigma \cup N)^*$. - \item $S \in N$ --- стартовый нетерминал. - \end{itemize} -\end{definition} - -Конъюнктивная грамматика генерирует строки, выводя их из начального символа, так же, как это происходит в контекстно-свободных грамматиках в параграфе~\ref{CFG}. Промежуточные строки, используемые в процессе вывода, являются формулами следующего вида: - -\begin{definition}\label{Definition of conjunctive formula} - Пусть $G = (\Sigma,N,P,S)$ --- конъюнктивная грамматика. Множество конъюнктивных формул $ \mathcal{F}$ определяется индуктивно: - \begin{itemize} - \item Пустая строка $\varepsilon$ --- конъюнктивная формула. - \item Любой символ из $(\Sigma \cup N)$ --- формула. - \item Если $\mathcal{A}$ и $\mathcal{B}$ непустые формулы, тогда $\mathcal{AB}$ --- формула. - \item Если $\mathcal{A}_1,\ldots,\mathcal{A}_n$ $(n \geqslant 1)$ --- формула, тогда $(\mathcal{A}_1\&\ldots\&\mathcal{A}_n)$ --- формула. - \end{itemize} -\end{definition} - -\begin{definition} - Пусть $G = (\Sigma,N,P,S)$ --- конъюнктивная грамматика. Аналогично определению отношения непосредственной выводимости в контекстно-свободной грамматике~\ref{def derivability in CFG} определим $\xRightarrow[G]{}$ как отношение непосредственной выводимости на множестве конъюнктивных формул. - \begin{itemize} - \item Любой нетерминал в любой формуле может быть перезаписан телом любого правила для этого терминала заключенным в скобки. То есть для любых $s^{'},s^{''} \in (\Sigma \cup N \cup \{(, \&, )\})^*$ и $A\in N$, таких что $s^{'}As^{''}$ --- формула, и для всех правил вида $A \rightarrow \alpha_1\&\ldots\&\alpha_n \in P$, имеем $s^{'}As^{''}\xRightarrow[G]{}s^{'}(\alpha_1\&\ldots\&\alpha_n)s^{''}$. - \item Если формула содержит подформулу в виде конъюнкции одной или нескольких одинаковых терминальных строк, заключенных в скобки, тогда подформула может быть перезаписана терминальной строкой без скобок. То есть для любых $s^{'},s^{''} \in (\Sigma \cup N \cup \{(, \&, )\})^*$, $(n \geqslant 1)$ и $w \in \Sigma^*$, таких что $s^{'}(w\&\ldots\&w)s^{''}$ --- формула, имеем $s^{'}(w\&\ldots\&w)s^{''}\xRightarrow[G]{}s^{'}ws^{''}$. - \end{itemize} - Как и в случае контекстно-свободной грамматики обозначим $\xRightarrow[G]{}^*$ рефлексивное транзитивное замыкание отношения $\xRightarrow[G]{}$. -\end{definition} - -\begin{definition} - Пусть $G = (\Sigma,N,P,S)$ --- конъюнктивная грамматика. Язык, порождаемый формулой, это множество всех терминальных строк выводимых из этой формулы: $L_{G}(\mathcal{A}) = \{w\in\Sigma^* \mid \mathcal{A} \xRightarrow[G]{}^*w\}$. Очевидно, что язык порождаемый грамматикой, это язык порождаемый стартовым нетерминалом $S$ : $L(G) = L_{G}(S) = L(S)$. -\end{definition} - -\begin{theorem}\label{Theorem language generated by a formula} - Пусть $G = (\Sigma,N,P,S)$ --- конъюнктивная грамматика. Пусть $\mathcal{A}_1,\ldots,\mathcal{A}_n,\mathcal{B}$ --- формулы, $A \in N$, $a \in \Sigma$. Тогда, - \begin{enumerate} - \item $L(\varepsilon) = \{\varepsilon\}$. - \item $L(a) = \{a\}$. - \item $L(A) = \bigcup_{A \rightarrow \alpha_1\&\ldots\&\alpha_n \in P} L((\alpha_1\&\ldots\&\alpha_m))$. - \item $L(\mathcal{AB}) = L(\mathcal{A})*L(\mathcal{B})$ - \item $L((\mathcal{A}_1\&\ldots\&\mathcal{A}_n)) = \bigcap_{i = 1}^{n}L(\mathcal{A}_i)$. - \end{enumerate} -\end{theorem} - -Теорема~\ref{Theorem language generated by a formula} уже подразумевает интерпретацию грамматики как системы уравнений. Используем математический подход, чтобы лучше охарактеризовать конъюнктивные языки с помощью систем уравнений. - -\begin{definition}[Выражение] - Пусть $\Sigma$ конечный непустой алфавит. Пусть $X = \{X_1,\ldots,X_N\}$ вектор переменных. Выражение над алфавитом $\Sigma$, зависящее от переменных $X$, определяется индуктивно: - \begin{itemize} - \item $\varepsilon$ --- выражение. - \item Любой символ $a\in\Sigma$ --- выражение. - \item Любая переменная $X_i\in X$ --- выражение. - \item Если $\phi_1$ и $\phi_2$ выражения, то $\phi_1\phi_2, (\phi_1\mid\phi_2), (\phi_1\&\phi_2)$ также выражения. - \end{itemize} - Заметим, что любая формула, в терминах определения~\ref{Definition of conjunctive formula}, является выражением, где нетерминалы формулы это переменные выражения. С другой стороны, любое выражение, не содержащее дизъюнкции, формула. -\end{definition} - -Предположим, что переменные $X_i$ приняли в качестве значений слова из языка над алфавитом $\Sigma$. Определим значение всего выражения. - -\begin{definition}[Значение выражения]\label{Value of conjunctive expression} - Пусть $L = (L_1,\ldots,L_n) (L_i \subseteq \Sigma^*)$ вектор из $n$ языков над $\Sigma$, где $n \geqslant 1$. Пусть $\phi$ выражение над $\Sigma$, зависящее от переменных $X_1,\ldots,X_n$. Значение выражения $\phi$ на векторе $L$ --- это язык над тем же алфавитом $\Sigma$. Обозначим его $\phi(L)$ и определим индуктивно на структуре выражения: - \begin{itemize} - \item $\varepsilon(L) = \{\varepsilon\}$. - \item $a(L) = \{a\}$ для любого $a\in\Sigma$. - \item $X_i(L) = L_i$ для любого $X_i \in X$. - \item $\phi_1\phi_2 = \phi_1(L) * \phi_2(L), (\phi_1\mid\phi_2)(L) = \phi_1(L) \cup \phi_2(L), (\phi_1\&\phi_2)(L) = \phi_1(L) \cap \phi_2(L)$ для любых выражений $\phi_1$ и $\phi_2$. - \end{itemize} -\end{definition} - -Обобщим определение~\ref{Value of conjunctive expression} на случай вектора выражений. - -\begin{definition}[Значение вектора выражений] - Пусть $L = (L_1,\ldots,L_n) (L_i \subseteq \Sigma^*)$ вектор из $n$ языков над $\Sigma$, где $n \geqslant 1$. Пусть $\phi_1,\ldots,\phi_m$ выражения над $\Sigma$, зависящее от переменных $X_1,\ldots,X_n$. Значение вектора выражений $P = (\phi_1,\ldots,\phi_m)$ на векторе $L$ --- это вектор языков $P(L) = (\phi_1(L),\ldots,\phi_m(L))$ над тем же алфавитом $\Sigma$. -\end{definition} - -Зададим частичный порядок относительно включения $``\preccurlyeq"$ на множестве языков и расширим его на вектора языков длины $n$: $(L_1^{'},\ldots,L_n^{'})\preccurlyeq(L_1^{''},\ldots,L_n^{''})$ если и только если $L_i^{'} \subseteq L_i^{''}$ для любого $1\leqslant i \leqslant n$ - -\begin{definition}\label{Definition a conjuctive system of equations} - $X = P(X)$ система уравнений над алфавитом $\Sigma$ и $X = \{X_1,\ldots,X_n\}$, где $P = (\phi_1,\ldots,\phi_n)$ вектор выражений над алфавитом $\Sigma$, зависящий от $X$. - - Вектор языков $L = (L_1,\ldots,L_n)$ является решением системы уравнений если $L = P(L)$. - - Наименьшее решение $L$ это вектор языков, такой что для любого другого сравнимого вектора языков $L^{'}$ выполняется $L \preccurlyeq L^{'}$. -\end{definition} - -Заметим, что оператор $P$ на множестве $2^{\Sigma}\times\ldots\times2^{\Sigma}$, что решение системы~\ref{Definition a conjuctive system of equations} это неподвижная точка $P$ и что наименьшее решение системы это наименьшая неподвижная точка оператора $P$. - -\begin{theorem}\label{Theorem of a least fixed point solution} - Для любой системы из определения~\ref{Definition a conjuctive system of equations} с переменными $X_1,\ldots,X_n$, оператор $P = (\phi_1,\ldots,\phi_n)$ имеет наименьшую неподвижную точку $L = (L_1,\ldots,L_n) = \lim_{i\to\infty}P^{i}\underbrace{(\varnothing,\ldots,\varnothing)}_n$. -\end{theorem} - -Приведем пример конъюнктивной грамматики. - -\begin{example}[Пример конъюнктивной грамматики] - Следующая конъюнктивная грамматика $G$ порождает язык $\{a^nb^nc^n\mid n \geq 0\}$: - - \begin{align*} - 1.\ S &\to A B \& D C \\ - 2.\ A &\to a A \mid \varepsilon \\ - 3.\ B &\to b B c \mid \varepsilon \\ - 4.\ C &\to c C \mid \varepsilon \\ - 5.\ D &\to aDb \mid \varepsilon - \end{align*} - - Легко видеть, что $L(AB) = \{a^ib^jc^k\mid j = k\}$ и $L(DC) = \{a^ib^jc^k\mid i = j\}$. Тогда $L(S) = L(AB) \cap L(DC) = \{a^nb^nc^n\mid n \geq 0\}$. - - В этой грамматике строка $abc$ может быть получена следующим образом. Для начала представим грамматику в виде системы уравнений: - \begin{align*} - S &= A B \cap D C \\ - A &= \{a\}A \cup \varepsilon \\ - B &= \{b\}B\{c\} \cup \varepsilon \\ - C &= \{c\}C \cup \varepsilon \\ - D &= \{a\}D\{b\} \cup \varepsilon - \end{align*} - Используя теорему~\ref{Theorem of a least fixed point solution}, будем итеративно вычислять $P^{i}\underbrace{(\varnothing,\ldots,\varnothing)}_5$. На каждом шаге будем подставлять все терминальные строки из языков, порожденных нетерминалами на предыдущем шаге, в соответствующие нетерминалы правой части каждого уравнения и записывать получившиеся терминальные строки в языки нетерминалов текущего шага. Продолжаем до тех пор пока язык, порождаемый нетерминалом $S$, не будет содержать терминальную строку $``abc''$. - \begin{enumerate} - \item На начальном этапе имеем $P^{0}(\varnothing,\ldots,\varnothing) = (S: \varnothing, A: \varnothing, B: \varnothing, C: \varnothing, D: \varnothing)$ - \item Подставляем в первое уравнение терминальные строки из шага 1 в соответствующие нетерминалы, т.е. - \begin{align*} - S: \varnothing &= \varnothing\varnothing \cap \varnothing\varnothing \\ - A: \{\varepsilon\} &= \{a\}\varnothing \cup \{\varepsilon\} \\ - B: \{\varepsilon\} &= \{b\}\varnothing\{c\} \cup \{\varepsilon\} \\ - C: \{\varepsilon\} &= \{c\}\varnothing \cup \{\varepsilon\} \\ - D: \{\varepsilon\} &= \{a\}\varnothing\{b\} \cup \{\varepsilon\} - \end{align*} - В конце итерации получаем $P^{1}(\varnothing,\ldots,\varnothing) = (S: \varnothing, A: \{\varepsilon\}, B: \{\varepsilon\}, C: \{\varepsilon\}, D: \{\varepsilon\})$ - \item Делаем еще одну итерацию, - \begin{align*} - S: \{\varepsilon\} &= \{\varepsilon\}\{\varepsilon\} \cap \{\varepsilon\}\{\varepsilon\} \\ - A: \{a, \varepsilon\} &= \{a\}\{\varepsilon\} \cup \{\varepsilon\} \\ - B: \{bc, \varepsilon\} &= \{b\}\{\varepsilon\}\{c\} \cup \{\varepsilon\} \\ - C: \{c, \varepsilon\} &= \{c\}\{\varepsilon\} \cup \{\varepsilon\} \\ - D: \{ab, \varepsilon\} &= \{a\}\{\varepsilon\}\{b\} \cup \{\varepsilon\} - \end{align*} - В конце итерации получаем $P^{2}(\varnothing,\ldots,\varnothing) = (S: \{\varepsilon\}, A: \{a, \varepsilon\}, B: \{bc, \varepsilon\}, C: \{c, \varepsilon\}, D: \{ab, \varepsilon\})$ - \item Еще одна итерация, - \begin{align*} - S: \{\fbox{abc}, \varepsilon\} &= \{a, \varepsilon\}\{bc, \varepsilon\} \cap \{ab, \varepsilon\}\{c, \varepsilon\} \\ - A: \{a, aa, \varepsilon\} &= \{a\}\{a, \varepsilon\} \cup \{\varepsilon\} \\ - B: \{bc, bbcc, \varepsilon\} &= \{b\}\{bc, \varepsilon\}\{c\} \cup \{\varepsilon\} \\ - C: \{c, cc, \varepsilon\} &= \{c\}\{c, \varepsilon\} \cup \{\varepsilon\} \\ - D: \{ab, aabb, \varepsilon\} &= \{a\}\{ab, \varepsilon\}\{b\} \cup \{\varepsilon\} - \end{align*} - В конце итерации получили $P^{3}(\varnothing,\ldots,\varnothing) = (S: \{\fbox{abc}, \varepsilon\}, A: \{a, aa, \varepsilon\}, B: \{bc, bbcc, \varepsilon\}, C: \{c, cc, \varepsilon\}, D: \{ab, aabb, \varepsilon\})$. Заметим, что терминальная строка $``abc"$ появилась в языке, который порождает стартовый нетерминал $S$. Т.е. терминальная строка $``abc"$ выводима в грамматике $G$, что и требовалось показать. - \end{enumerate} - - Заметим, что строку $``abc"$ также можно получить применением правил вывода. здесь цифра над стрелкой соответствует номеру примененного правила. - \begin{align*} - S &\xRightarrow{1}(AB\&DC) \\ - &\xRightarrow{2}(aAB\&DC) \xRightarrow{2} (a\varepsilon B\&DC) \\ - &\xRightarrow{3}(abBc\&DC) \xRightarrow{3}(ab\varepsilon c\&DC) \\ - &\xRightarrow{5}(abc\&aDbC) \xRightarrow{5}(abc\&a\varepsilon bC) \\ - &\xRightarrow{4}(abc\&abcC) \xRightarrow{4}(abc\&abc\varepsilon) \\ - &\Rightarrow(abc\&abc) \Rightarrow abc - \end{align*} -\end{example} - -\begin{example} - Конъюнктивная грамматика $G$ для языка $L = \{wcw \mid w \in \{a, b\}^*\}$: - \begin{align*} - S &\to C \& D \\ - C &\to aCa \mid aCb \mid bCa \mid bCb \mid c \\ - D &\to aA\&aD \mid bB\&bD \mid cE \\ - A &\to aAa \mid aAb \mid bAa \mid bAb \mid cEa \\ - B &\to aBa \mid aBb \mid bBa \mid bBb \mid cEb \\ - E &\to aE \mid bE \mid \varepsilon - \end{align*} -\end{example} - -Подробнее о конъюнктивных грамматиках можно прочитать в статьях~\cite{DBLP:journals/jalc/Okhotin01, Okhotin2002, DBLP:journals/tcs/Okhotin03a, f60a33d409364914be560cac0e54b12c}. - -Дадим определение булевой грамматики. - -\begin{definition} - \textit{Булевой грамматикой} называется $G = (\Sigma,N,P,S)$, где: - \begin{itemize} - \item $\Sigma$ и $N$ --- дизъюнктивные конечные непустые множества терминалов и нетерминалов. - \item $P$ --- конечное множество продукций, каждая вида - \[ - A\rightarrow \alpha_1\&...\&\alpha_m\&\neg\beta_1\&...\&\neg\beta_n - \] - ,где $A \in N, m, n >=0, m+n \geq 1$ и $\alpha_i,\beta_j \in (\Sigma \cup N)^*$. - \item $S \in N$ --- стартовый нетерминал. - \end{itemize} -\end{definition} - -Приведем пример булевой грамматики. - -\begin{example} - Следующая булева грамматика порождает язык $\{a^mb^nc^n\mid m,n \geq 0, m \neq n \}$: - - \begin{align*} - S &\to A B \& \neg D C \\ - A &\to a A \mid \varepsilon \\ - B &\to b B c \mid \varepsilon \\ - C &\to c C \mid \varepsilon \\ - D &\to aDb \mid \varepsilon - \end{align*} - - Очевидно, что $L(AB) = \{a^mb^nc^n\mid m,n \in \mathbb{N}\}$ и $L(DC) = \{a^nb^nc^m\mid m,n \in \mathbb{N}\}$. Тогда $L(AB)\cap\overline{L(DC)} = \{a^mb^nc^n\mid m,n \geq 0, m \neq n \}$. -\end{example} - -Подробнее о булевых грамматиках можно прочитать в статьях~\cite{Okhotin:2003:BG:1758089.1758123,Okhotin:2014:PMM:2565359.2565379}. - -Определим бинарную нормальную форму конъюнктивной грамматики. -\begin{definition}[Бинарная нормальная форма] - Конъюнктивная грамматика $G = (\Sigma, N, P, S)$ находится в бинарной нормальной форме, если каждое правило из P имеет вид, - \begin{itemize} - \item $A \rightarrow B_1 C_1 \& \ldots\& B_m C_m$, где $m \geqslant 1; A,B_i,C_i \in N$. - \item $A \rightarrow a$, где $A \in N, a \in \Sigma$. - \item $S \rightarrow \varepsilon$, если только $S$ не содержится в правой части всех правил. - \end{itemize} -\end{definition} - -\begin{theorem}\label{Binary normal form conjunctive grammar theorem} - Для каждой конъюнктивной грамматики $G$ можно построить конъюнктивную грамматику в бинарной нормальной форме $G^{'}$, такую что $L(G) = L(G^{'})$. -\end{theorem} -Доказательство теоремы~\ref{Binary normal form conjunctive grammar theorem} описано в статье~\cite{DBLP:journals/jalc/Okhotin01}. - - - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item !!! -% \item !!! -%\end{enumerate} diff --git a/tex/Context-Free_Languages.tex b/tex/Context-Free_Languages.tex deleted file mode 100644 index de7551a..0000000 --- a/tex/Context-Free_Languages.tex +++ /dev/null @@ -1,588 +0,0 @@ -\chapter{Контекстно-свободные языки и грамматики}\label{CFG} - -Из всего многообразия нас будут интересовать прежде всего контекстно-свободные грамматики. - -\begin{definition} -\textit{Контекстно-свободная грамматика} --- это четвёрка вида $\langle \Sigma, N, P, S \rangle$, где -\begin{itemize} - \item $\Sigma$ --- это терминальный алфавит; - \item $N$ --- это нетерминальный алфавит; - \item $P$ --- это множество правил (продукций), таких что каждая продукция имеет вид $N_i \to \alpha$, где $N_i \in N$ и $\alpha \in \{\Sigma \cup N\}^* \cup {\varepsilon}$; - \item $S$ --- стартовый нетерминал. - Отметим, что $\Sigma \cap N = \varnothing$. -\end{itemize} -\end{definition} - -\begin{example} -Грамматика, задающая язык целых чисел в двоичной записи без лидирующих нулей: $G = \langle \{0, 1, -\}, \{S, N, A\}, P, S \rangle$, где $P$ определено следующим образом: -\begin{align*} - S & \rightarrow 0 \mid N \mid - N \\ - N & \rightarrow 1 A \\ - A & \rightarrow 0 A \mid 1 A \mid \varepsilon\\ -\end{align*} -\end{example} -При спецификации грамматики часто опускают множество терминалов и нетерминалов, оставляя только множество правил. При этом нетерминалы часто обозначаются прописными латинскими буквами, терминалы --- строчными, а стартовый нетерминал обозначается буквой~$S$. Мы будем следовать этим обозначениям, если не указано иное. - - -\begin{definition}\label{def derivability in CFG} - \textit{Отношение непосредственной выводимости}. Мы говорим, что последовательность терминалов и нетерминалов $\gamma \beta \delta$ \textit{непосредственно выводится из} $\gamma \alpha \delta$ \textit{при помощи правила} $\alpha \rightarrow \beta$ ($\gamma \alpha \delta \Rightarrow \gamma \beta \delta$), если - \begin{itemize} - \item $\alpha \rightarrow \beta \in P$ - \item $\gamma, \delta \in \{\Sigma \cup N\}^* \cup {\varepsilon}$ - \end{itemize} -\end{definition} - -\begin{definition} - \textit{Рефлексивно-транзитивное замыкание отношения} --- это наименьшее рефлексивное и транзитивное отношение, содержащее исходное. -\end{definition} - -\begin{definition} -\textit{Отношение выводимости} является рефлексивно-транзитивным замыканием отношения непосредственной выводимости; обозначается $\derives$. -\begin{itemize} - \item $\alpha \derives \beta$ означает $\exists \gamma_0, \dots \gamma_k \in \{\Sigma \cup N\}^* \cup {\varepsilon}: \ \alpha \derives[] \gamma_0 \derives[] \gamma_1 \derives[] \dots \derives[] \gamma_{k-1} \derives[] \gamma_{k} \derives[] \beta$ - \item Транзитивность: $\forall \alpha, \beta, \gamma \in \{\Sigma \cup N\}^* \cup {\varepsilon}: \ \alpha \derives \beta, \beta \derives \gamma \Rightarrow \alpha \derives \gamma$ - \item Рефлексивность: $\forall \alpha \in \{\Sigma \cup N\}^* \cup {\varepsilon}: \ \alpha \derives \alpha$ - \item $\alpha \derives \beta$ --- $\alpha$ выводится из $\beta$ - \item $\alpha \derives[k] \beta$ --- $\alpha$ выводится из $\beta$ за $k$ шагов - \item $\alpha \derives[+] \beta$ --- при выводе использовалось хотя бы одно правило грамматики -\end{itemize} -\end{definition} - - -\begin{example} -Пример вывода цепочки $-1101$ в грамматике: -\begin{align*} - S &\rightarrow 0 \mid N \mid - N \\ - N &\rightarrow 1 A \\ - A &\rightarrow 0 A \mid 1 A \mid \varepsilon\\ -\end{align*} -\[ - S \Rightarrow - N \Rightarrow - 1 A \Rightarrow - 1 1 A \derives - 1 1 0 1 A \Rightarrow - 1 1 0 1 -\] -\end{example} - - -\begin{definition}[Вывод слова в грамматике] -Слово $\omega \in \Sigma^*$ \textit{выводимо в грамматике} $\langle \Sigma, N, P, S \rangle$, если существует некоторый вывод этого слова из начального нетерминала $S \derives \omega$. - -\end{definition} - -\begin{definition} -\textit{Левосторонний вывод}. На каждом шаге вывода заменяется самый левый нетерминал. -\end{definition} - -\begin{definition} - \textit{Правосторонний вывод}. На каждом шаге вывода заменяется самый правый нетерминал. -\end{definition} - - -\begin{example} -Приведем пример левостороннего вывода цепочки $cbaa$ в грамматике: -\begin{align*} - S &\rightarrow A A \mid s \\ - A &\rightarrow A A \mid B b \mid a \\ - B &\rightarrow c \mid d -\end{align*} - Жирным выделен нетерминал, заменяемый на каждом шагу вывода. - \[ \boldsymbol{S} \derives[] \boldsymbol{A} A \derives[] \boldsymbol{B} b A \derives[] c b \boldsymbol{A} \derives[] c b \boldsymbol{A} A \derives[] c b a \boldsymbol{A} \derives[] c b a a \] -\end{example} - -Аналогично левостороннему можно определить правосторонний вывод. - -\begin{definition} -\textit{Язык, задаваемый грамматикой} --- множество строк, выводимых в грамматике $L(G) = \{ \omega \in \Sigma^* \mid S \derives \omega \}$. -\end{definition} - -\begin{definition} - Грамматики $G_1$ и $G_2$ называются \textit{эквивалентными}, если они задают один и тот же язык: $L(G_1) = L(G_2)$ -\end{definition} - - -\begin{example} Пример эквивалентных грамматик для языка целых чисел в двоичной системе счисления. - - \begin{tabular}{p{0.4\textwidth} | p{0.5\textwidth}} - \[ - \begin{aligned} - \Sigma & = \{ 0, 1, - \} \\ - N & = \{ S, N, A \} \\~\\ - S & \rightarrow 0 \mid N \mid - N \\ - N & \rightarrow 1 A \\ - A & \rightarrow 0 A \mid 1 A \mid \varepsilon\\ - \end{aligned} - \] - & - \[ - \begin{aligned} - \Sigma & = \{ 0, 1, - \} \\ - N & = \{ S, A \} \\~\\ - S & \rightarrow 0 \mid 1 A \mid - 1 A \\ - A & \rightarrow 0 A \mid 1 A \mid \varepsilon\\ - \end{aligned} - \] - \end{tabular} - -\end{example} - - -\begin{definition} - \textit{Неоднозначная грамматика} --- грамматика, в которой существует 2 и более левосторонних (правосторонних) выводов для одного слова. -\end{definition} - -\begin{example} - Неоднозначная грамматика для правильных скобочных последовательностей: -\[ - S \to (S) \mid S S \mid \varepsilon -\] -Два различных левосторонних вывода строки $()()()$: -\[S \derives[] S S \derives [] (S) S \derives[] () S \derives[] () S S \derives[] () (S) S \derives[] () () S \derives[] () () (S) \derives[] () () ()\] -\[S \derives[] S S \derives[] S S S \derives[] (S) S S \derives[] () S S \derives[] () (S) S \derives[] () () S \derives[] () () (S) \derives[] () () ()\] -\end{example} - -\begin{definition} - \textit{Однозначная грамматика} --- грамматика, в которой существует не более одного левостороннего (правостороннего) вывода для каждого слова. -\end{definition} - -\begin{example} - Однозначная грамматика для правильных скобочных последовательностей -\[ - S \to (S)S \mid \varepsilon -\] -\end{example} - -\begin{definition} - \textit{Существенно неоднозначные языки} --- языки, для которых невозможно построить однозначную грамматику. -\end{definition} - -\begin{example} - Пример существенно неоднозначного языка -\[\{a^n b^n c^m \mid n, m \in \mathds{Z}\} \cup \{a^n b^m c^m \mid n,m \in \mathds{Z}\}\] -\end{example} - -\section{Дерево вывода}\label{sect:DerivTree} -В некоторых случаях не достаточно знать порядок применения правил. -Необходимо структурное представление вывода цепочки в грамматике. -Таким представлением является \textit{дерево вывода}. -\begin{definition} -Деревом вывода цепочки $\omega$ в грамматике $G=\langle \Sigma, N, S, P \rangle$ называется дерево, удовлетворяющее следующим свойствам. - -\begin{enumerate} - \item Помеченное: метка каждого внутреннего узла --- нетерминал, метка каждого листа --- терминал или $\varepsilon$. - \item Корневое: корень помечен стартовым нетерминалом. - \item Упорядоченное. - \item В дереве может существовать узел с меткой $N_i$ и сыновьями $M_j \dots M_k$ только тогда, когда в грамматике есть правило вида $N_i \to M_j \dots M_k$. - \item Крона образует исходную цепочку $\omega$. -\end{enumerate} -\end{definition} - -\begin{example} - Построим дерево вывода цепочки $ababab$ в грамматике - - \[ G = \langle \{a,b\}, \{S\}, S, \{S \to a \ S \ b \ S, S \to \varepsilon\} \rangle \] - -\begin{center} - \input{figures/cfl/tree0.tex} -\end{center} - -\end{example} - -\begin{theorem} - Пусть $G = \langle \Sigma, N, P, S \rangle$ --- КС-грамматика. - Вывод $S \derives \alpha$, где $\alpha \in (N \cup \Sigma)^*, \alpha \neq \varepsilon$ существует $\Leftrightarrow$ существует дерево вывода в грамматике $G$ с кроной $\alpha$. -\end{theorem} - -\section{Пустота КС-языка} - -\begin{theorem} - Существует алгоритм, определяющий, является ли язык, порождаемый КС грамматикой, пустым. -\end{theorem} - -\begin{proof} - Следующая лемма утверждает, что если в КС языке есть выводимое слово, то существует другое выводимое слово с деревом вывода не глубже количества нетерминалов грамматики. - Для доказательства теоремы достаточно привести алгоритм, последовательно строящий все деревья глубины не больше количества нетерминалов грамматики, и проверяющий, являются ли такие деревья деревьями вывода. - Если в результате работы алгоритма не удалось построить ни одного дерева, то грамматика порождает пустой язык. -\end{proof} - -\begin{lemma} - Если в данной грамматике выводится некоторая цепочка, то существует цепочка, дерево вывода которой не содержит ветвей длиннее $m$, где $m$ --- количество нетерминалов грамматики. -\end{lemma} - -\begin{proof} - Рассмотрим дерево вывода цепочки $\omega$. Если в нем есть 2 узла, соответствующих одному нетерминалу A, обозначим их $n_1$ и $n_2$. - - Предположим, $n_1$ расположен ближе к корню дерева, чем $n_2$. - - Вывод цепочки $\omega$ имеет следующий вид: - \[S \derives \alpha A_{n_1} \beta \derives \alpha \omega_1 \beta; S \derives \alpha \gamma A_{n_2} \delta \beta \derives \alpha \gamma \omega_2 \delta \beta \derives \omega,\] - при этом $\omega_2$ является подцепочкой $\omega_1$. - - Заменим в изначальном дереве узел $n_1$ на $n_2$. Полученное дерево является деревом вывода цепочки $\alpha \omega_2 \delta$. - - Повторяем процесс замены одинаковых нетерминалов до тех пор, пока в дереве не останутся только уникальные нетерминалы. - - В полученном дереве не может быть ветвей длины большей, чем $m$. - - По построению оно является деревом вывода. -\end{proof} - - -\section{Нормальная форма Хомского} -\label{section:CNF} - -\begin{definition} -Контекстно-свободная грамматика $\langle \Sigma, N, P, S\rangle$ находится в \textit{Нормальной Форме Хомского}, если она содержит только правила следующего вида: - -\begin{itemize} - \item $A \to B C \text{, где } A, B, C \in N$, а стартовый нетерминал $S$ не содержится в правой части правила. - \item $A \to a \text{, где } A \in N, a \in \Sigma$ - \item $S \to \varepsilon$: только из стартового нетерминала выводима пустая строка. -\end{itemize} -\end{definition} - -\begin{theorem} -Любую КС грамматику можно преобразовать в НФХ. -\end{theorem} - -\begin{proof} - Алгоритм преобразования в НФХ состоит из следующих шагов: - - \begin{itemize} - \item Замена неодиночных терминалов - \item Удаление длинных правил - \item Удаление $\varepsilon$-правил - \item Удаление цепных правил - \item Удаление бесполезных нетерминалов - \end{itemize} - - То, что каждый из этих шагов преобразует грамматику к эквивалентной, при этом является алгоритмом, доказано в следующих леммах. -\end{proof} - -\begin{lemma} - Для любой КС-грамматики можно построить эквивалентную, которая не содержит правила с неодиночными терминалами. -\end{lemma} - -\begin{proof} - Каждое правило $A \to B_0 B_1 \dots B_k, k \geq 1$ заменить на множество правил, где $C_i$ --- новый нетерминал: -\begin{align*} - A & \to C_0 C_1 \dots C_k \\ - C_0 & \to B_0 \\ - C_1 & \to B_1 \\ - & \dots \\ - C_k & \to B_k -\end{align*} -\end{proof} - -\begin{lemma} - Для любой КС-грамматики можно построить эквивалентную, которая не содержит правил длины больше 2. -\end{lemma} - -\begin{proof} - Каждое правило $A \to B_0 B_1 \dots B_k, k \geq 2$ заменить на множество правил: - \begin{align*} - A & \to B_0 C_0 \\ - C_0 & \to B_1 C_1 \\ - & \dots \\ - C_{k-3} & \to B_{k-2} C_{k-2} \\ - C_{k-2} & \to B_{k-1} B_k - \end{align*} -\end{proof} - - -\begin{lemma} - Для любой КС-грамматики можно построить эквивалентную, не содержащую $\varepsilon$-правил. -\end{lemma} - -\begin{proof} - Рекурсивно определим $\varepsilon$-правила: - \begin{itemize} - \item $A \to \varepsilon$ --- $\varepsilon$-правило - \item $A \to B_0 \dots B_k$ --- $\varepsilon$-правило, если $\forall i: \ B_i$ --- $\varepsilon$-правило. - \end{itemize} - - Каждое правило $A \to B_0 B_1 \dots B_k$ заменяем на множество правил, где каждое $\varepsilon$-правило удалено во всех возможных комбинациях. -\end{proof} - -\begin{lemma} - Для любой КС-грамматики можно построить эквивалентную, не содержащую цепные правила. -\end{lemma} - -\begin{proof} - \textit{Цепное правило} --- правило вида $A \to B\text{, где } A, B \in N$. - \textit{Цепная пара} --- упорядоченная пара $(A,B)$, в которой $A\derives B$, используя только цепные правила. - - Алгоритм: - \begin{enumerate} - \item Найти все цепные пары в грамматике $G$. - Найти все цепные пары можно по индукции: - Базис: $(A,A)$ --- цепная пара для любого нетерминала, так как $A\derives A$ за ноль шагов. - Индукция: Если пара $(A,B_0)$ --- цепная, и есть правило $B_0 \to B_1$, то $(A,B_1)$ --- цепная пара. - \item Для каждой цепной пары $(A,B)$ добавить в грамматику $G'$ все правила вида $A \to a$, где $B \to a$ --- нецепное правило из $G$. - \item Удалить все цепные правила -\end{enumerate} -Пусть $G$ --- контекстно-свободная грамматика. $G'$ --- грамматика, полученная в результате применения алгоритма к $G$. Тогда $L(G)=L(G')$. -\end{proof} - -\begin{definition} -Нетерминал $A$ называется \textit{порождающим}, если из него может быть выведена конечная терминальная цепочка. Иначе он называется \textit{непорождающим}. -\end{definition} - -\begin{lemma} - Можно удалить все бесполезные (непорождающие) нетерминалы -\end{lemma} - -\begin{proof} - После удаления из грамматики правил, содержащих непорождающие нетерминалы, язык не изменится, так как непорождающие нетерминалы по определению не могли участвовать в выводе какого-либо слова. - - Алгоритм нахождения порождающих нетерминалов: - \begin{enumerate} - \item Множество порождающих нетерминалов пустое. - \item Найти правила, не содержащие нетерминалов в правых частях и добавить нетерминалы, встречающихся в левых частях таких правил, в множество. - \item Если найдено такое правило, что все нетерминалы, стоящие в его правой части, уже входят в множество, то добавить в множество нетерминалы, стоящие в его левой части. - \item Повторить предыдущий шаг, если множество порождающих нетерминалов изменилось. -\end{enumerate} -В результате получаем множество всех порождающих нетерминалов грамматики, а все нетерминалы, не попавшие в него, являются непорождающими. Их можно удалить. -\end{proof} - -\begin{example} - Приведем в Нормальную Форму Хомского однозначную грамматику правильных скобочных последовательностей: $S \to a S b S \mid \varepsilon$ - - Первым шагом добавим новый нетерминал и сделаем его стартовым: - \begin{align*} - S_0 &\to S \\ - S &\to a S b S \mid \varepsilon - \end{align*} - Заменим все терминалы на новые нетерминалы: - \begin{align*} - S_0 &\to S \\ - S &\to L S R S \mid \varepsilon \\ - L &\to a \\ - R &\to b - \end{align*} - Избавимся от длинных правил: - \begin{align*} - S_0 &\to S \\ - S &\to L S' \mid \varepsilon \\ - S' &\to S S'' \\ - S'' &\to R S \\ - L &\to a \\ - R &\to b - \end{align*} - Избавимся от $\varepsilon$-продукций: - \begin{align*} - S_0 &\to S \mid \varepsilon \\ - S &\to L S' \\ - S' &\to S'' \mid S S'' \\ - S'' &\to R \mid R S \\ - L &\to a \\ - R &\to b - \end{align*} - Избавимся от цепных правил: - \begin{align*} - S_0 &\to L S' \mid \varepsilon \\ - S &\to L S' \\ - S' &\to b \mid R S \mid S S'' \\ - S'' &\to b \mid R S \\ - L &\to a \\ - R &\to b - \end{align*} -\end{example} - -\begin{definition}\label{defn:wCNF} -Контекстно-свободная грамматика $\langle \Sigma, N, P, S\rangle$ находится в \textit{ослабленной Нормальной Форме Хомского}, если она содержит только правила следующего вида: - -\begin{itemize} - \item $A \to B C \text{, где } A, B, C \in N$ - \item $A \to a \text{, где } A \in N, a \in \Sigma$ - \item $A \to \varepsilon \text{, где } A \in N$ -\end{itemize} - -То есть ослабленная НФХ отличается от НФХ тем, что: -\begin{enumerate} - \item $\varepsilon$ может выводиться из любого нетерминала - \item $S$ может появляться в правых частях правил -\end{enumerate} -\end{definition} - -\section{Лемма о накачке} - -\begin{lemma} -Пусть $L$ --- контекстно-свободный язык над алфавитом $\Sigma$, тогда существует такое $n$, что для любого слова $\omega \in L$, $|\omega| \geq n$ найдутся слова $u,v,x,y,z\in \Sigma^*$, для которых верно: $uvxyz = \omega, vy\neq \varepsilon,|vxy|\leq n$ и для любого $k \geq 0$ $uv^kxy^kz \in L$. -\end{lemma} - -Идея доказательства леммы о накачке. - -\begin{enumerate} - \item Для любого КС языка можно найти грамматику в нормальной форме Хомского. - \item Очевидно, что если брать достаточно длинные цепочки, то в дереве вывода этих цепочек, на пути от корня к какому-то листу обязательно будет нетерминал, встречающийся минимум два раза. Если $m$ --- количество нетерминалов в НФХ, то длины $2^{m+1}$ должно хватить. Это и будет $n$ из леммы. - \item Возьмём путь, на котором есть хотя бы дважды повторяется некоторый нетерминал. Скажем, это нетерминал $N_1$. Пойдём от листа по этому пути. Найдём первое появление $N_1$. Цепочка, задаваемая поддеревом для этого узла --- это $x$ из леммы. - \item Пойдём дальше и найдём второе появление $N_1$. Цепочка, задаваемая поддеревом для этого узла --- это $vxy$ из леммы. - \item Теперь мы можем копировать кусок дерева между этими повторениями $N_1$ и таким образом накачивать исходную цепочку. -\end{enumerate} - -Надо только проверить выполнение ограничений на длины. - -Нахождение разбиения и пример накачки продемонстрированы на рисунках~\ref{fig:pumping1} и~\ref{fig:pumping2}. - -\begin{figure} -\centering -\input{figures/cfl/pumping1.tex} -\caption{Разбиение цепочки для леммы о накачке} -\label{fig:pumping1} -\end{figure} - -\begin{figure} -\centering - \begin{subfigure}[b]{0.4\textwidth} - \centering - \input{figures/cfl/pumping0.tex} - \caption{$k = 0$.} - % \label{fig:f1} - \end{subfigure} -\hfill - \begin{subfigure}[b]{0.4\textwidth} - \centering - \input{figures/cfl/pumping2.tex} - \caption{$k = 2$.} - % \label{fig:f2} - \end{subfigure} -\caption{Пример накачки цепочки с рисунка~\ref{fig:pumping1}} -\label{fig:pumping2} -\end{figure} - - -Для примера предлагается проверить неконтекстно-свободность языка $L=\{a^nb^nc^n \mid n>0\}$. - - -\section{Замкнутость КС языков относительно операций} - - -\begin{theorem} -Контекстно-свободные языки замкнуты относительно следующих операций: -\begin{enumerate} - \item Объединение: если $L_1$ и $L_2$ --- контекстно-свободные языки, то и $L_3 = L_1 \cup L_2$ --- контекстно-свободный. - \item Конкатенация: если $L_1$ и $L_2$ --- контекстно-свободные языки, то и $L_3 = L_1 \cdot L_2$ --- контекстно-свободный. - \item Замыкание Клини: если $L_1$ --- контекстно-свободный, то и $L_2 = \bigcup\limits_{i=0}^{\infty} L_1^i $ --- контекстно-свободный. - \item Разворот: если $L_1$ --- контекстно-свободный, то и $L_2 = {L_1}^r = \{ l^r \mid l \in L_1\}$ является контекстно-свободным. - \item Пересечение с регулярными языками: если $L_1$ --- контекстно-свободный, а $L_2$ --- регулярный, то $L_3 = L_1 \cap L_2$ --- контекстно-свободный. - \item Разность с регулярными языками: если $L_1$ --- контекстно-свободный, а $L_2$ --- регулярный, то $L_3 = L_1 \setminus L_2$ --- контекстно-свободный. -\end{enumerate} -\end{theorem} -Для доказательства пунктов 1--4 можно построить КС грамматику нового языка имея грамматики для исходных. -Будем предполагать, что множества нетерминальных символов различных грамматик для исходных языков не пересекаются. -\begin{enumerate} -\item $G_1=\langle\Sigma_1,N_1,P_1,S_1\rangle$ --- грамматика для $L_1$, $G_1=\langle\Sigma_2,N_2,P_2,S_2\rangle$ --- грамматика для $L_2$, тогда $G_3=\langle\Sigma_1 \cup \Sigma_2, N_1 \cup N_2 \cup \{S_3\}, P_1 \cup P_2 \cup \{S_3 \to S_1 \mid S_2\} ,S_3\rangle$ --- грамматика для $L_3$. - -\item $G_1=\langle\Sigma_1,N_1,P_1,S_1\rangle$ --- грамматика для $L_1$, $G_1=\langle\Sigma_2,N_2,P_2,S_2\rangle$ --- грамматика для $L_2$, тогда $G_3=\langle\Sigma_1 \cup \Sigma_2, N_1 \cup N_2 \cup \{S_3\}, P_1 \cup P_2 \cup \{S_3 \to S_1 S_2\} ,S_3\rangle$ --- грамматика для $L_3$. - -\item $G_1=\langle\Sigma_1,N_1,P_1,S_1\rangle$ --- грамматика для $L_1$, тогда $G_2=\langle\Sigma_1, N_1 \cup \{S_2\}, P_1 \cup \{S_2 \to S_1 S_2\ \mid \varepsilon\}, S_2\rangle$ --- грамматика для $L_2$. - -\item $G_1=\langle\Sigma_1,N_1,P_1,S_1\rangle$ --- грамматика для $L_1$, тогда $G_2=\langle\Sigma_1, N_1, \{N^i \to \omega^R \mid N^i \to \omega \in P_1 \}, S_1\rangle$ --- грамматика для $L_2$. -\end{enumerate} - -Чтобы доказать замкнутость относительно пересечения с регулярными языками, построим по КС грамматике рекурсивный автомат $R_1$, по регулярному выражению --- детерминированный конечный автомат $R_2$, и построим их прямое произведение $R_3$. -Переходы по терминальным символам в новом автомате возможны тогда и только тогда, когда они возможны одновременно и в исходном рекурсивном автомате и в исходном конечном. -За рекурсивные вызовы отвечает исходный рекурсивный автомат. -Значит цепочка принимается $R_3$ тогда и только тогда, когда она принимается одновременно $R_1$ и $R_2$: так как состояния $R_3$ --- это пары из состояния $R_1$ и $R_2$, то по трассе вычислений $R_3$ мы всегда можем построить трассу для $R_1$ и $R_2$ и наоборот. - -Чтобы доказать замкнутость относительно разности с регулярным языком, достаточно вспомнить, что регулярные языки замкнуты относительно дополнения, и выразить разность через пересечение с дополнением: -\[ - L_1 \setminus L_2 = L_1 \cap \overline{L_2} -\] -\qed - -\begin{theorem} -Контекстно-свободные языки не замкнуты относительно следующих операций: -\begin{enumerate} - \item Пересечение: если $L_1$ и $L_2$ --- контекстно-свободные языки, то и $L_3 = L_1 \cap L_2$ --- не контекстно-свободный. - \item Разность: если $L_1$ и $L_2$ --- контекстно-свободные языки, то и $L_3 = L_1 \setminus L_2$ --- не контекстно-свободный. -\end{enumerate} -\end{theorem} - -Чтобы доказать незамкнутость относительно пресечения, рассмотрим языки $L_1 = \{a^n b^n c^k \mid n \geq 0, k \geq 0\}$ и $L_2 = \{a^k b^n c^n \mid n \geq 0, k \geq 0\}$. -Очевидно, что $L_1$ и $L_2$ --- контекстно-свободные языки. -Рассмотрим $L_3 = L_1 \cap L_2 = \{a^n b^n c^n \mid n \geq 0\}$. -$L_3$ не является контекстно-свободным по лемме о накачке для контекстно-свободных языков. - -Чтобы доказать незамкнутость относительно разности проделаем следующее. -\begin{enumerate} -\item Рассмотрим языки $L_4 = \{a^m b^n c^k \mid m \neq n, k \geq 0\}$ и $L_5 = \{a^m b^n c^k \mid n \neq k, m \geq 0\}$. -Эти языки являются контекстно-свободными. -Это легко заметить, если знать, что язык $L'_4 = \{a^m b^n c^k \mid 0 \leq m < n, k \geq 0\}$ задаётся следующей грамматикой: -\begin{align*} -S \to & S c & T \to & a T b \\ -S \to & T & T \to & T b \\ - & & T \to & b. -\end{align*} - -\item Рассмотрим язык $L_6 = \overline{L'_6} = \overline{\{a^n b^m c^k \mid n \geq 0, m \geq 0, k \geq 0\}}$. Данный язык является регулярным. - -\item Рассмотрим язык $L_7 = L_4 \cup L_5 \cup L_6$ --- контекстно-свободный, так как является объединением контекстно-свободных. - -\item Рассмотрим $\overline{L_7} = \{a^n b^n c^n \mid n \geq 0\} = L_3$: $L_4$ и $L_5$ задают языки с правильным порядком символов, но неравным их количеством, $L_6$ задаёт язык с неправильным порядком символов. -Из предыдущего пункта мы знаем, что $L_3$ не является контекстно-свободным. - -\end{enumerate} - -\qed - -\section{Рекурсивные автоматы и сети} - -Рекурсивный автомат или сеть --- это представление контекстно-свободных грамматик, обобщающее конечные автоматы. -В нашей работе мы будем придерживаться термина \textbf{рекурсивный автомат}. -Классическое определение рекурсивного автомата выглядит следующим образом. - -\begin{definition} -Рекурсивный автомат --- это кортеж вида $\langle N, \Sigma, S, D \rangle$, где -\begin{itemize} -\item $N$ --- нетерминальный алфавит; -\item $\Sigma$ --- терминальный алфавит; -\item $S$ --- стартовый нетерминал; -\item $D$ --- конечный автомат над $N \cup \Sigma$ в котором стартовые и финальные состояния помечены подмножествами $N$. -\end{itemize} -\end{definition} - -Построение РКА по грамматике. - -Допущение о том, что все состояния занумерованы подряд и уникальны. - -Немного ссылок на работы по РКА. - -Построим рекурсивный автомат для грамматики $G$: -\begin{align*} -S &\to a S b \\ -S &\to a b \\ -\end{align*} - - -\begin{align} -\label{input1} - \begin{tikzpicture}[node distance=2.5cm,shorten >=1pt,on grid,auto] - \node[state, initial] (q_0) {$0 \{S\}$}; - \node[state] (q_1) [right=of q_0] {$1$}; - \node[state] (q_2) [right=of q_1] {$2$}; - \node[state, accepting] (q_3) [right=of q_2] {$3\{S\}$}; - \path[->] - (q_0) edge node {a} (q_1) - (q_1) edge node {S} (q_2) - (q_2) edge node {b} (q_3) - (q_1) edge[bend left, above] node {b} (q_3); - \end{tikzpicture} -\end{align} - -Используем стандартные обозначения для стартовых и финальных состояний. -Дополнительно в стартовых и финальных состояниях укажем нетерминалы, для которых эти состояния стартовые/финальные. - -В некоторых случаях рекурсивный автомат можно рассматривать как конечный автомат над смешанным алфавитом. -Именно такой взгляд мы будем использовать при изложении алгоритма. - -Пример интерпретации конечного автомата. - - - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item Постройте дерево вывода цепочки $w=aababb$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ S \}, S \rangle$. -% \item Постройте все левосторонние выводы цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$. -% \item Постройте все правосторонние выводы цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$. -% \item \label{t1}Постройте все деревья вывода цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$, соответствующие левосторонним выводам. -% \item \label{t2}Постройте все деревья вывода цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$, соответствующие правосторонним выводам. -%\end{enumerate} diff --git a/tex/DerivativesForCFPQ.tex b/tex/DerivativesForCFPQ.tex deleted file mode 100644 index 8b9d1e7..0000000 --- a/tex/DerivativesForCFPQ.tex +++ /dev/null @@ -1,156 +0,0 @@ -\chapter{Производные для КС запросов}\label{chpt:CFPQ_Derivatives} - -В данной главе мы рассмотрим производные Бжозовского и их возможное применение. - -\section{Производные} - -Впервые производные формальных языков были определены в 1964 году учёным Янушем Бжозовским (в честь него они и были названы). Он определил это понятие для регулярных языков, предложил алгоритм для вычисления производной обобщенного регулярного выражения, также Бжозовский занимался исследованием свойств производных {\cite{Brzozowski1964}}. - -Изначально всё начиналось с производных регулярных языков, и в главе мы в основном будем говорить именно о них. - -Рассмотрим формальное определение производной произвольного языка: - -\begin{definition} - \textit{Производной языка $\mathcal{L}$ по символу а} называется язык $\mathcal{L'} = \partial_{a}(\mathcal{L}) = \{w \mid aw \in \mathcal{L}\}$, где: - \begin{itemize} - \item $\mathcal{L} \subseteq \{w \mid w \in \Sigma^*\}$ --- произвольный язык над алфавитом $\Sigma$ - \item $a \in \Sigma$ --- символ, по которому берётся производная - \end{itemize} - То есть фактически производная языка --- это суффиксы слов, начинающихся на символ, по которому язык дифференцируется. -\end{definition} - -\begin{example}[Производные языка] -Рассмотрим язык $\mathcal{L} = \{pen, plain, day, pray\}$ и несколько языков, порождённых от него с помощью дифференцирования: -\begin{enumerate} - \item $\mathcal{L'} = \partial_{p}(\mathcal{L}) = \{en, lain, ray\}$ - \item $\mathcal{L''} = \partial_{e}(\mathcal{L'}) = \{n\}$ - \item $\mathcal{L'''} =\partial_{n}(\mathcal{L''}) = \{\varepsilon\}$ -\end{enumerate} -\end{example} - -\section{Принадлежность языку} - -С помощью производных ествественным образом можно проверять принадлежность слова регулярному языку. -Есть регулярное выражение $R$ и язык, порожденный этим регулярным выражением $L(R)$. Возьмём произвольное слово $w$ и зададимся вопросом: $w \in L(R)$? - -Пусть $w = a_{0}a_{1}... a_{n-1}$, а новый язык $\mathcal{L'}$ получен последовательным дифференцирование исходного языка $L(R)$ по каждому из символов слова $w$, то есть $\mathcal{L'} = \partial_{a_{n-1}}(...\partial_{a_{1}}(\partial_{a_{0}}(L(R)))...)$. В таком случае принадлежность $w$ языку $L(R)$ определяется наличием пустого слова в итоговом языке: $\varepsilon \in \mathcal{L'} \Rightarrow w \in L(R)$. - -\begin{example} -Дан язык $\mathcal{L} = \{pen, plain, day, pray\}$. Принадлежат ли данному языку слова $pen$, $pet$? -\begin{itemize} - \item $\partial_{p}(\mathcal{L}) = \{en, lain, ray\} \Rightarrow \partial_{e}(\partial_{p}(\mathcal{L})) = \{n\} \Rightarrow \partial_{n}(\partial_{e}(\partial_{p}(\mathcal{L}))) = \{\varepsilon\}$. А значит, $pen \in \mathcal{L}$ - \item $\partial_{p}(\mathcal{L}) = \{en, lain, ray\} \Rightarrow \partial_{e}(\partial_{p}(\mathcal{L})) = \{n\} \Rightarrow \partial_{t}(\partial_{e}(\partial_{p}(\mathcal{L}))) = \emptyset$. Значит, $pet \notin \mathcal{L}$ -\end{itemize} - -\end{example} - -Описанный выше механизм является основной идеей всех алгоритмом, которые стоятся на производных. - -\section{Построение производных} - -Концептуально понятно, как выглядят производные, но хотелось бы уметь считать их алгоритмически, причём сохраняя конструктивное представление языка. Например, для КС грамматики, вычисляя её производную, строится другая КС грамматика. - -Рассмотрим алгоритм вычисления производной для регулярных языков, которые представлены как регулярные выражения. Пусть $r_{1}$ и $r_{2}$ --- два регулярных выражения, $a$ --- произвольный терминальный символ. Определим вспомогательную функцию N --- Nullable, которая проверяет язык на содержание в нём пустого слова $\varepsilon$: - -\begin{align*} - N(\varepsilon) &= true \\ - N(a) &= false \\ - N(r_{1} \cdot r_{2}) &= N(r_{1}) \land N(r_{2}) \\ - N(r_{1} \mid r_{2}) &= N(r_{1}) \lor N(r_{2}) \\ - N(r^*) &= true -\end{align*} - -Теперь мы готовы перейти непосредственно к вычислению производной по символу $a$: - -\begin{align*} - \partial_{a}(\emptyset) &= \emptyset \\ - \partial_{a}(\varepsilon) &= \emptyset \\ - \partial_{a}(b) &= \begin{cases} - \emptyset, & \mbox{if } a \neq b \\ - \varepsilon, & \mbox{otherwise} \end{cases} \\ - \partial_{a}(r_{1} \cdot r_{2}) &= \begin{cases} - \partial_{a}(r_{1}) \cdot r_{2} \mid \partial_{a}(r_{2}) & \mbox{if } N(r_{1}) = \mbox{true} \\ - \partial_{a}(r_{1}) \cdot r_{2}, & \mbox{otherwise} \end{cases} \\ - \partial_{a}(r_{1} \mid r_{2}) &= \partial_{a}(r_{1}) \mid \partial_{a}(r_{2}) \\ - \partial_{a}(r^*) &= \partial_{a}(r) \cdot r^* -\end{align*} - -Все правила, за исключением, может быть, последнего, достаточно тривиальны. Последнее доказывается по индукции, но особо любопытные могут руками вычислить для первой пары слагаемых и рассмотреть закономерность. - -Приводить подобный алгоритм для КС языков мы не будем, но важно понимать, что он есть, и идея не сильно отличается от алгоритма для регулярных языков. - -\section{Задача достижимости} -Используя производные, можно решать задачу достижимости. Даны регулярный запрос и граф, для простоты зафиксируем стартовую вершину. Для решения задачи достижимости при помощи производных рекурсивно выполняем следующее: - -\begin{enumerate} - \item При переходе по ребру дифференцируем запрос по метке на нём - \item Передаём эту производную вдоль ребра в следующую вершину - \item В этой следующей вершине производная запоминается, если ранее не встречалось регулярное выражение, которое порождается тот же язык (таким образом формируется набор регулярных выражений, порождающих языки, которые уже передовались на вершину). В противном случае -- терминируемся. -\end{enumerate} - -После того, как вышеописанный алгоритм завершился для всех вершин, проходим по ним и ищем в их наборах Nullable регулярные выражения, которые и сигнализируют о том, что путь из стартовой веришны в данную вершину существует. - -Некоторые замечания: - -\begin{itemize} - \item Если алгоритм запускается не на одной вершине, а сразу на нескольких, передаются вдоль рёбер не просто производные, а пары: (стартовая вершина, производная). - \item Что мы в общем случае делаем с циклами, чтобы задача считалась алгоритмически? Разбиваем граф на наибольшие по включению компоненты сильной связности с связями между ними, стягиваем компоненты. Тогда граф превращается в дек, в котором проблем с нетерминируемостью нет, а с компонентами сильной связности разбираемся отдельно. Для этого достаточно рассмотреть одну такую компоненту: если есть цикл, то по нему можно ходить, только если в запросе есть применение звезды Клини, и, как нам уже известно, производная запроса данной операции --- конечная конструкция. В итоге мы сможем, переходя по вершинами, прийти к моменту, когда внутри компоненты в наборах производных вершин новых элементов не будет прибавляться, а значит, мы можем закончить алгоритм. -\end{itemize} - -Рассмотрим решение задачи достижимости с помощью производных на конкретном примере: - -\begin{example} -Даны регулярный запрос $R = a^* \mid a^* \cdot b$ и граф $\mathcal{G}$: - - \begin{center} - \begin{tikzpicture}[shorten >=1pt,on grid,auto] - \node[state] (q_0) {$0$}; - \node[state] (q_1) [above right=of q_0] {$1$}; - \node[state] (q_2) [right=of q_0] {$2$}; - \node[state] (q_3) [right=of q_2] {$3$}; - \path[->] - (q_0) edge node {a} (q_1) - (q_1) edge node {a} (q_2) - (q_2) edge node {a} (q_0) - (q_2) edge[bend left, above] node {b} (q_3) - (q_3) edge[bend left, below] node {b} (q_2); - \end{tikzpicture} - \end{center} - -Стартовая веришина --- вершина графа $\mathcal{G}$ с индексом 0. Хотим проверить существование путей из вершины 0 до других вершин графа по $R$. Заведем 4 множества, в которых будем хранить регулярные выражения, передаваемые в конкретную вершину: $M_{0}$ --- для вершины с индексом 0, $M_{1}$ --- для вершины с индексом 1 и так далее. - -\begin{enumerate} - \item Начинаем идти вдоль ребра с меткой $a$ из вершины 0 в 1. Дифференцируем наш запрос по данной метке: $\partial_{a}(R) = \partial_{a}(a^* \mid a^* \cdot b) = \partial_{a}(a^*) \mid \partial_{a}(a^* \cdot b) = \partial_{a}(a) \cdot a^* \mid \partial_{a}(a^*) \cdot b \mid \partial_{a}(b) = a^* \mid a^* \cdot b = R$. Запоминаем эту производную в $M_{1}$: $M_{1} = \{R\}$ - \item Аналогично идём из вершины 1 в вершину 2 по $a$. В итоге в $M_{2}$ также будет находиться R. - \item В вершине 2 параллельно идём по метке $a$ в 0 и по метке $b$ в вершину с индексом 3. - \begin{enumerate} - \item В первом потоке при переходе по $a$ мы дифференцируем $R$ по a, получаем также $R$, кладем его в $M_{0}$. Пытаясь продолжить эти вычисления в данном потоке, мы обнаружим, что при переходе по $a$ из вершины 0 в вершину 1 наша производная будет снова R, но в множестве $M_{1}$ $R$ уже находится, а значит, данная ветка вычислений терминируется. - \item При переходе по $b$ диффиринцируем переданную производную $R$: $\partial_{b}(R) = \partial_{b}(a^* \mid a^* \cdot b) = \partial_{b}(a^*) \mid \partial_{b}(a^* \cdot b) = \partial_{b}(a) \cdot a^* \mid \partial_{b}(a^*) \cdot b \mid \partial_{b}(b) = \partial_{b}(b) = \varepsilon$. Запоминаем производную в $M_{3}$: $M_{3} = \{\varepsilon\}$. Дифференцируем её по $b$ при переходе из 3 в 2. Кладём в $M_{2}$ $\partial_{b}(\varepsilon) = \emptyset$. Tаким oбразом, $M_{2} = \{R, \emptyset\}$. На данном этапе можно терминирироваться, т.к. для достижимости нам интересны регулярные выражения, порождающий $\varepsilon$, но дифференцируя $\emptyset$ по каким-либо меткам, мы снова получаем $\emptyset$. При "честном" вычислении, в нашем случае пустое множество будет добавлено во все множества $M_{i}$, и уже после этого вычисление завершится. - \end{enumerate} - \item Теперь у нас есть сформированные множества производных для всех вершин и мы можем говорить о достижимости до данных вершин из стартовой. Рассмотрим $M_{0}$, $M_{0} = \{R\}$. Содержит ли $R$ $\varepsilon$? Посчитаем для этого нашу функцию Nullable: $N(R) = N(a^* \mid a^* \cdot b) = N(a^*) \mid N(a^* \cdot b) = true \mid N(a^* \cdot b) = true$. Из чего следует, что существует путь из вершины 0 в вершину 0. Аналогичным способом заключаем, что веришны 2 и 3 достижимы из вершины 0 (т.к. в их множества также содержится $R$). Рассмотрим $M_{3} = \{\varepsilon\}$. $N(\varepsilon) = true$, значит, вершина 3 тоже достижима из 0. Алгоритм завершён. -\end{enumerate} - -Таким образом, выполнив указанный выше алгоритм для данного примера, мы определили, что из стартовой вершины с индексом 0 достижимы все вершины графа $\mathcal{G}$. -\end{example} - -\section{Парсинг на производных} - -Статьи~\cite{DBLP:journals/corr/abs-1010-5023,Adams:2016:CPP:2908080.2908128,Might:2011:PDF:2034574.2034801,andersenparsing} -Реализации. -На Scala~\footnote{\url{https://github.com/djspiewak/parseback}}, на Racket~\footnote{\url{https://bitbucket.org/ucombinator/derp-3/src/86bca8a720231e010a3ad6aefd1aa1c0f35cbf6b/src/derp.rkt?at=master&fileviewer=file-view-default}}. - -\section{Адаптация для КС запросов} - -Для регулярных запросов над графами~\cite{Nole:2016:RPQ:2949689.2949711}. -Хорошо работают в распределённых системах, в которых реализовван параллелизм уровня вершин. -Например Google Pregel. - - - -\section{Вопросы и задачи} -\begin{enumerate} - \item Предъявить несколько выводов для одной цепочки. - \item Построить выводы - \item Построить деревья вывода !!! Перенести из раздела про SPPF -\end{enumerate} - diff --git a/tex/FLPQ.tex b/tex/FLPQ.tex deleted file mode 100644 index 22dfdda..0000000 --- a/tex/FLPQ.tex +++ /dev/null @@ -1,146 +0,0 @@ -\chapter[Пути с ограничениями в терминах формальных языков]{Задача о поиске путей с ограничениями в терминах формальных языков}\label{chpt:FLPQ} - - - -В данной главе сформулируем постановку задачи о поиске путей в графе с ограничениями. -Также мы приведём несколько примеров областей, в которых применяются алгоритмы решения этой задачи. - -\section{Постановка задачи } - - -Пусть нам дан конечный ориентированный помеченный граф $\mathcal{G}=\langle V,E,L \rangle$. -Функция $\omega(\pi) = \omega((v_0, l_0, v_1),(v_1,l_1,v_2),\dots,(v_{n-1},l_{n-1},v_n)) = l_0 \cdot l_1 \cdot \ldots \cdot l_{n-1} $ строит слово по пути посредством конкатенации меток рёбер вдоль этого пути. -Очевидно, для пустого пути данная функция будет возвращать пустое слово, а для пути длины $n > 0$ --- непустое слово длины $n$. - -Если теперь рассматривать задачу поиска путей, то окажется, что то множество путей, которое мы хотим найти, задаёт множество слов, то есть язык. -А значит, критерий поиска мы можем сформулировать следующим образом: нас интересуют такие пути, что слова, составленные из меток вдоль них, принадлежат заданному языку. -\begin{definition} \label{def1} - \textit{Задача поиска путей с ограничениями в терминах формальных языков} заключается в поиске множества путей $\Pi = \{\pi \mid \omega(\pi) \in \mathcal{L}\}$. - -\end{definition} - -В задаче поиска путей мы можем накладывать дополнительные ограничения на путь (например, чтобы он был простым, кратчайшим или Эйлеровым~\cite{kupferman2016eulerian}), но это уже другая история. - -Другим вариантом постановки задачи является задача достижимости. - -\begin{definition} \label{def2} - \textit{Задача достижимости} заключается в поиске множества пар вершин, для которых найдется путь с началом и концом в этих вершинах, что слово, составленное из меток рёбер пути, будет принадлежать заданному языку. - $\Pi' = \{(v_{i}, v_{j}) \mid \exists v_{i} \pi v_{j}, \omega(\pi) \in \mathcal{L}\}$. - -\end{definition} - -При этом, множество $\Pi$ может являться бесконечным, тогда как $\Pi'$ конечно, по причине конечности графа $\mathcal{G}$. - -Язык $\mathcal{L}$ может принадлежать разным классам и быть задан разными способами. Например, он может быть регулярным, контекстно-свободным, или многокомпонентным контекстно-свободным. - -Если $\mathcal{L}$ --- регулярный, $\mathcal{G}$ можно рассматривать как недетерминированный конечный автомат (НКА), в котором все вершины являются одновременно и стартовыми, и конечными. -Тогда задача поиска путей, в которой $\mathcal{L}$ --- регулярный, сводится к пересечению двух регулярных языков. - -Более подробно мы рассмотрим случай, когда $\mathcal{L}$ --- контекстно-свободный язык. - -Путь $G = \langle \Sigma, N, P \rangle$ --- контекстно-свободная грамматика. -Будем считать, что $L \subseteq \Sigma$. -Мы не фиксируем стартовый нетерминал в определении грамматики, поэтому, чтобы описать язык, задаваемый ей, нам необходимо отдельно зафиксировать стартовый нетерминал. -Таким образом, будем говорить, что $L(G,N_i) = \{ w \mid N_i \xRightarrow[G]{*} w \}$ --- это язык задаваемый грамматикой $G$ со стартовым нетерминалом $N_i$. - -\begin{example} - Пример задачи поиска путей. - - Дана грамматика $G$, задающая язык $\mathcal{L} = a^n b^n$: - \begin{align*} - S &\to a b \\ - S &\to a S b - \end{align*} - И дан граф $\mathcal{G}:$ - \begin{center} - \input{figures/graph/graph0.tex} - \end{center} - - Кратчайшими путями, принадлежащими множеству $\Pi = \{\pi \mid \omega(\pi) \in \mathcal{L}\}$, являются: - - \begin{center} - \input{figures/flpq/path1.tex} - \end{center} - - \begin{center} - \input{figures/flpq/path2.tex} - \end{center} - -\end{example} - - -\section{О разрешимости задачи} - -Задачи из определения \ref{def1} и \ref{def2} сводятся к построению пересечения языка $\mathcal{L}$ и языка, задаваемого путями графа, $R$. -А мы для обсуждения разрешимости задачи рассмотрим более слабую постановку задачи: - -\begin{definition} - Необходимо проверить, что существует хотя бы один такой путь $\pi$ для данного графа, для данного языка $\mathcal{L}$, что $\omega(\pi) \in \mathcal{L}$. - -\end{definition} - -Эта задача сводится к проверке пустоты пересечения языка $\mathcal{L}$ c $R$ --- регулярным языком, задаваемым графом. От класса языка $\mathcal{L}$ зависит её разрешимость: - -\begin{itemize} - \item Если $\mathcal{L}$ регулярный, то получаем задачу пересечения двух регулярных языков: - - $\mathcal{L} \cap R = R'$. - $R'$ --- также регулярный язык. - Проверка регулярного языка на пустоту --- разрешимая проблема. - - \item Если $\mathcal{L}$ контекстно-свободный, то получаем задачу - - $\mathcal{L} \cap R = CF$ --- контекстно-свободный. - Проверка контекстно-свободного языка на пустоту --- разрешимая проблема. - - \item Помимо иерархии Хомского существуют и другие классификации языков. - Так например, класс конъюнктивных (Conj) - языков~\cite{DBLP:journals/jalc/Okhotin01} - является строгим расширением контекстно-свободных языков и все так же позволяет полиномиальный синтаксический анализ. - - Пусть $\mathcal{L}$ --- конъюнктивный. При пересечении конъюнктивного и регулярного языков получается конъюнктивный ($\mathcal{L} \cap R = Conj$), а проблема проверки Conj на пустоту не разрешима~\cite{DBLP:journals/tcs/Okhotin03a}. - - \item Ещё один класс языков из альтернативной иерархии, не сравнимой с Иерархией Хомского, --- MCFG (multiple context-free grammars)~\cite{SEKI1991191}. - Как его частный случай --- TAG (tree adjoining grammar)~\cite{Joshi1997}. - - Если $\mathcal{L}$ принадлежит классу MCFG, то $\mathcal{L} \cap R$ также принадлежит MCFG. Проблема проверки пустоты MCFG разрешима~\cite{SEKI1991191}. - -\end{itemize} - -Существует ещё много других классификаций языков, но поиск универсальной иерархии до сих пор продолжается. - -Далее, для изучения алгоритмов решения, нас будет интересовать задача $R \cap CF$. - -\section{Области применения} - -Поиск путей с ограничениями в виде формальных языков широко применяется в различных областях. Ниже даны ключевые работы по применению поиска путей с контекстно-свободными ограничениями и ссылки на них для более детального ознакомления. - -\begin{itemize} - \item Межпроцедурный Статанализ кода. - Идея начала активно разрабатываться Томасом Репсом~\cite{Reps}. Далее последовал ряд, в том числе инженерных работ, применяющих достижимость с контекстно-свободными ограничениями для анализа указателей, анализа алиасов и других прикладных задач~\cite{LabelFlowCFLReachability,specificationCFLReachability,Zheng}. - \item Графовые БД. Впервые задача сформулирована Михалисом Яннакакисом~\cite{Yannakakis}. Запросы с контекстно-свободными ограничениями нашли своё применение различных областях. - \begin{itemize} - \item Социальные сети~\cite{Hellings2015PathRF}. - \item RDF обработка~\cite{10.1007/978-3-319-46523-4_38}. - \item Биоинформатика~\cite{cfpqBio}. - \end{itemize} - -\end{itemize} - -%\begin{itemize} -% \item OpenCypher~\cite{Kuijpers:2019:ESC:3335783.3335791} -% \item J.Hellings. CFPQ~\cite{hellingsRelational,hellings2015querying,Hellings2015PathRF} -% \item Zhang. CFPQ on rdf graphs~\cite{10.1007/978-3-319-46523-4_38} -% \item Bradford~\cite{bradford2007quickest,ward2008distributed,bradford2016fast,Bradford:2008:LCG:1373936.1373946} -%\end{itemize} - - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item Пусть есть граф. Задайте грамматику для поиска всех путей, таких, что.... -% \item Существует ли в графе !!! путь из А в Б, такой что!!! -% \item Для графа !!! постройте все пути, удовлетворяющие !!!! -% -% \item Задача 1 -% \item Задача 2 -%\end{enumerate} diff --git a/tex/FormalLanguageConstrainedReachabilityLectureNotes.bib b/tex/FormalLanguageConstrainedReachabilityLectureNotes.bib deleted file mode 100644 index 2738d4b..0000000 --- a/tex/FormalLanguageConstrainedReachabilityLectureNotes.bib +++ /dev/null @@ -1,1984 +0,0 @@ -@article{cohen2016parsing, - title={Parsing linear context-free rewriting systems with fast matrix multiplication}, - author={Cohen, Shay B and Gildea, Daniel}, - journal={Computational Linguistics}, - volume={42}, - number={3}, - pages={421--455}, - year={2016}, - publisher={MIT Press One Rogers Street, Cambridge, MA 02142-1209, USA journals-info~…} -} - -@inproceedings{nakanishi1997efficient, - title={An efficient recognition algorithm for multiple context-free languages}, - author={Nakanishi, Ryuichi and Takada, Keita and Seki, Hiroyuki}, - booktitle={In Proceedings of the Fifth Meeting on Mathematics of Language, MOL5}, - year={1997}, - organization={Citeseer} -} - -@inproceedings{zhang2013fast, - title={Fast algorithms for Dyck-CFL-reachability with applications to alias analysis}, - author={Zhang, Qirun and Lyu, Michael R and Yuan, Hao and Su, Zhendong}, - booktitle={Proceedings of the 34th ACM SIGPLAN Conference on Programming Language Design and Implementation}, - pages={435--446}, - year={2013} -} - -@article{kodumal2004set, - title={The set constraint/CFL reachability connection in practice}, - author={Kodumal, John and Aiken, Alex}, - journal={ACM Sigplan Notices}, - volume={39}, - number={6}, - pages={207--218}, - year={2004}, - publisher={ACM New York, NY, USA} -} - -@article{reps2000undecidability, - title={Undecidability of context-sensitive data-dependence analysis}, - author={Reps, Thomas}, - journal={ACM Transactions on Programming Languages and Systems (TOPLAS)}, - volume={22}, - number={1}, - pages={162--186}, - year={2000}, - publisher={ACM New York, NY, USA} -} - -@inproceedings{yan2011demand, - title={Demand-driven context-sensitive alias analysis for Java}, - author={Yan, Dacong and Xu, Guoqing and Rountev, Atanas}, - booktitle={Proceedings of the 2011 International Symposium on Software Testing and Analysis}, - pages={155--165}, - year={2011} -} - -@inproceedings{bastani2015specification, - title={Specification inference using context-free language reachability}, - author={Bastani, Osbert and Anand, Saswat and Aiken, Alex}, - booktitle={Proceedings of the 42nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages}, - pages={553--566}, - year={2015} -} - -@inproceedings{zheng2008demand, - title={Demand-driven alias analysis for C}, - author={Zheng, Xin and Rugina, Radu}, - booktitle={Proceedings of the 35th annual ACM SIGPLAN-SIGACT symposium on Principles of programming languages}, - pages={197--208}, - year={2008} -} - -@inproceedings{huang2015scalable, - title={Scalable and precise taint analysis for android}, - author={Huang, Wei and Dong, Yao and Milanova, Ana and Dolby, Julian}, - booktitle={Proceedings of the 2015 International Symposium on Software Testing and Analysis}, - pages={106--117}, - year={2015} -} - -@article{sridharan2006refinement, - title={Refinement-based context-sensitive points-to analysis for Java}, - author={Sridharan, Manu and Bod{\'\i}k, Rastislav}, - journal={ACM SIGPLAN Notices}, - volume={41}, - number={6}, - pages={387--400}, - year={2006}, - publisher={ACM New York, NY, USA} -} - -@inproceedings{zhang2017context, - title={Context-sensitive data-dependence analysis via linear conjunctive language reachability}, - author={Zhang, Qirun and Su, Zhendong}, - booktitle={Proceedings of the 44th ACM SIGPLAN Symposium on Principles of Programming Languages}, - pages={344--358}, - year={2017} -} - -@article{seki1991multiple, - title={On multiple context-free grammars}, - author={Seki, Hiroyuki and Matsumura, Takashi and Fujii, Mamoru and Kasami, Tadao}, - journal={Theoretical Computer Science}, - volume={88}, - number={2}, - pages={191--229}, - year={1991}, - publisher={Elsevier} -} - -@book{Hopcroft+Ullman/79/Introduction, - added-at = {2009-05-20T01:29:36.000+0200}, - author = {Hopcroft, John E. and Ullman, Jeff D.}, - biburl = {https://www.bibsonomy.org/bibtex/26f42b10773b0f97be73d4e0d6b8db3bf/sriram0339}, - description = {First cut database}, - interhash = {0fb20598f4921085d9c5058fc8d95f00}, - intrahash = {6f42b10773b0f97be73d4e0d6b8db3bf}, - keywords = {imported}, - publisher = {Addison-Wesley Publishing Company}, - timestamp = {2009-05-20T01:29:37.000+0200}, - title = {Introduction to Automata Theory, Languages, and Computation}, - year = 1979 -} - -@inproceedings{Verbitskaia:2018:PCC:3241653.3241655, - author = {Verbitskaia, Ekaterina and Kirillov, Ilya and Nozkin, Ilya and Grigorev, Semyon}, - title = {Parser Combinators for Context-free Path Querying}, - booktitle = {Proceedings of the 9th ACM SIGPLAN International Symposium on Scala}, - series = {Scala 2018}, - year = {2018}, - isbn = {978-1-4503-5836-1}, - location = {St. Louis, MO, USA}, - pages = {13--23}, - numpages = {11}, - url = {http://doi.acm.org/10.1145/3241653.3241655}, - doi = {10.1145/3241653.3241655}, - acmid = {3241655}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {Context-Free Language Reachability, Context-Free Path Querying, GLL, Generalized LL, Graph Databases, Language-Constrained Path Problem, Neo4j, Parser Combinators, Scala}, -} - -@inproceedings{Mishin:2019:ECP:3327964.3328503, - author = {Mishin, Nikita and Sokolov, Iaroslav and Spirin, Egor and Kutuev, Vladimir and Nemchinov, Egor and Gorbatyuk, Sergey and Grigorev, Semyon}, - title = {Evaluation of the Context-Free Path Querying Algorithm Based on Matrix Multiplication}, - booktitle = {Proceedings of the 2Nd Joint International Workshop on Graph Data Management Experiences \& Systems (GRADES) and Network Data Analytics (NDA)}, - series = {GRADES-NDA'19}, - year = {2019}, - isbn = {978-1-4503-6789-9}, - location = {Amsterdam, Netherlands}, - pages = {12:1--12:5}, - articleno = {12}, - numpages = {5}, - url = {http://doi.acm.org/10.1145/3327964.3328503}, - doi = {10.1145/3327964.3328503}, - acmid = {3328503}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {CUDA, Context-free path querying, GPGPU, boolean matrix, context-free grammar, graph databases, matrix multiplication, transitive closure}, -} - -@article{Valiant:1975:GCR:1739932.1740048, - author = {Valiant, Leslie G.}, - title = {General Context-free Recognition in Less Than Cubic Time}, - journal = {J. Comput. Syst. Sci.}, - issue_date = {April, 1975}, - volume = {10}, - number = {2}, - month = apr, - year = {1975}, - issn = {0022-0000}, - pages = {308--315}, - numpages = {8}, - url = {http://dx.doi.org/10.1016/S0022-0000(75)80046-8}, - doi = {10.1016/S0022-0000(75)80046-8}, - acmid = {1740048}, - publisher = {Academic Press, Inc.}, - address = {Orlando, FL, USA}, -} - -@inproceedings{Yannakis, -author = {Yannakakis, Mihalis}, -year = {1990}, -month = {01}, -pages = {230-242}, -title = {Graph-Theoretic Methods in Database Theory.}, -doi = {10.1145/298514.298576} -} - -@inproceedings{Azimov:2018:CPQ:3210259.3210264, - author = {Azimov, Rustam and Grigorev, Semyon}, - title = {Context-free Path Querying by Matrix Multiplication}, - booktitle = {Proceedings of the 1st ACM SIGMOD Joint International Workshop on Graph Data Management Experiences \& Systems (GRADES) and Network Data Analytics (NDA)}, - series = {GRADES-NDA '18}, - year = {2018}, - isbn = {978-1-4503-5695-4}, - location = {Houston, Texas}, - pages = {5:1--5:10}, - articleno = {5}, - numpages = {10}, - url = {http://doi.acm.org/10.1145/3210259.3210264}, - doi = {10.1145/3210259.3210264}, - acmid = {3210264}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {GPGPU, context-free grammar, context-free path querying, graph databases, matrix multiplication, transitive closure}, -} - -@inproceedings{Grigorev:2017:CPQ:3166094.3166104, - author = {Grigorev, Semyon and Ragozina, Anastasiya}, - title = {Context-free Path Querying with Structural Representation of Result}, - booktitle = {Proceedings of the 13th Central \& Eastern European Software Engineering Conference in Russia}, - series = {CEE-SECR '17}, - year = {2017}, - isbn = {978-1-4503-6396-9}, - location = {St. Petersburg, Russia}, - pages = {10:1--10:7}, - articleno = {10}, - numpages = {7}, - url = {http://doi.acm.org/10.1145/3166094.3166104}, - doi = {10.1145/3166094.3166104}, - acmid = {3166104}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {CFPQ, GLL, LL, context-free grammar, graph database, graph parsing, path query, top-down parsing}, -} - -@inproceedings{Kuijpers:2019:ESC:3335783.3335791, - author = {Kuijpers, Jochem and Fletcher, George and Yakovets, Nikolay and Lindaaker, Tobias}, - title = {An Experimental Study of Context-Free Path Query Evaluation Methods}, - booktitle = {Proceedings of the 31st International Conference on Scientific and Statistical Database Management}, - series = {SSDBM '19}, - year = {2019}, - isbn = {978-1-4503-6216-0}, - location = {Santa Cruz, CA, USA}, - pages = {121--132}, - numpages = {12}, - url = {http://doi.acm.org/10.1145/3335783.3335791}, - doi = {10.1145/3335783.3335791}, - acmid = {3335791}, - publisher = {ACM}, - address = {New York, NY, USA}, -} - -@article{MEDEIROS201975, -title = "LL-based query answering over RDF databases", -journal = "Journal of Computer Languages", -volume = "51", -pages = "75 - 87", -year = "2019", -issn = "2590-1184", -doi = "https://doi.org/10.1016/j.cola.2019.02.002", -url = "http://www.sciencedirect.com/science/article/pii/S1045926X18301915", -author = "Ciro M. Medeiros and Martin A. Musicante and Umberto S. Costa", -keywords = "Context-Free graph patterns, Graph databases, RDF, SPARQL", -abstract = "We present a method based on top-down parsing techniques for evaluating context-free path queries on RDF Graph Databases. The syntax of the query language is based on SPARQL. The language extends SPARQL by allowing the use of non-terminal symbols of a context-free grammar to specify paths on the graph. In this manner, the language subsumes the definition of regular graph patterns present in SPARQL. Our query evaluator takes an RDF graph, a context-free grammar and a declarative query, and produces tuples of values. The query evaluator proceeds in two stages: Firstly, the RDF graph is enriched with edges representing paths which correspond to strings derived by the grammar. We show that this algorithm is correct and presents a cubic worst-case run-time complexity on the number of nodes in the graph, which is an improvement over some previous work. The second stage of the evaluator uses the produced graph to identify tuples of values defined by a declarative query. In order to validate our approach, we conducted experiments by using some popular ontologies as well as synthetic databases. We compare performance results of our method with some related work." -} - - -@INPROCEEDINGS{8249039, -author={P. G. {Bradford}}, -booktitle={2017 IEEE 8th Annual Ubiquitous Computing, Electronics and Mobile Communication Conference (UEMCON)}, -title={Efficient exact paths for dyck and semi-dyck labeled path reachability (extended abstract)}, -year={2017}, -volume={}, -number={}, -pages={247-253}, -keywords={computational complexity;directed graphs;formal languages;graph theory;matrix multiplication;reachability analysis;efficient exact paths;weighted digraph;exact path length problem;exact path problem;original edge weights;path solutions;labeled digraph;semiDyck languages;Dyck languages;labeled path problems;Grammar;Heuristic algorithms;Jacobian matrices;Costing;Algorithm design and analysis;Shortest path problem}, -doi={10.1109/UEMCON.2017.8249039}, -ISSN={}, -month={Oct},} - -@article{quadtree, -author = {El abbadi, Nidhal}, -year = {2014}, -month = {11}, -pages = {25-30}, -title = {An Efficient Storage Format for Large Sparse Matrices based on Quadtree}, -volume = {105}, -journal = {International Journal of Computer Applications} -} - -@InProceedings{10.1007/978-3-319-41579-6_22, -author="Verbitskaia, Ekaterina -and Grigorev, Semyon -and Avdyukhin, Dmitry", -editor="Mazzara, Manuel -and Voronkov, Andrei", -title="Relaxed Parsing of Regular Approximations of String-Embedded Languages", -booktitle="Perspectives of System Informatics", -year="2016", -publisher="Springer International Publishing", -address="Cham", -pages="291--302", -abstract="We present a technique for syntax analysis of a regular set of input strings. This problem is relevant for the analysis of string-embedded languages when a host program generates clauses of embedded language at run time. Our technique is based on a generalization of RNGLR algorithm, which, inherently, allows us to construct a finite representation of parse forest for regularly approximated set of input strings. This representation can be further utilized for semantic analysis and transformations in the context of reengineering, code maintenance, program understanding etc. The approach in question implements relaxed parsing: non-recognized strings in approximation set are ignored with no error detection.", -isbn="978-3-319-41579-6" -} - -@article{Lee:2002:FCG:505241.505242, - author = {Lee, Lillian}, - title = {Fast Context-free Grammar Parsing Requires Fast Boolean Matrix Multiplication}, - journal = {J. ACM}, - issue_date = {January 2002}, - volume = {49}, - number = {1}, - month = jan, - year = {2002}, - issn = {0004-5411}, - pages = {1--15}, - numpages = {15}, - url = {http://doi.acm.org/10.1145/505241.505242}, - doi = {10.1145/505241.505242}, - acmid = {505242}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {Boolean matrix multiplication, context-free grammar parsing}, -} - -@article{Chan2008, -author="Chan, Timothy M.", -title="All-Pairs Shortest Paths with Real Weights in $O(n^3/log{\thinspace}n)$ Time", -journal="Algorithmica", -year="2008", -month="Feb", -day="01", -volume="50", -number="2", -pages="236--243", -issn="1432-0541", -doi="10.1007/s00453-007-9062-1", -url="https://doi.org/10.1007/s00453-007-9062-1" -} - -@inproceedings{Williams:2010:SEP:1917827.1918339, - author = {Williams, Virginia Vassilevska and Williams, Ryan}, - title = {Subcubic Equivalences Between Path, Matrix and Triangle Problems}, - booktitle = {Proceedings of the 2010 IEEE 51st Annual Symposium on Foundations of Computer Science}, - series = {FOCS '10}, - year = {2010}, - isbn = {978-0-7695-4244-7}, - pages = {645--654}, - numpages = {10}, - url = {http://dx.doi.org/10.1109/FOCS.2010.67}, - doi = {10.1109/FOCS.2010.67}, - acmid = {1918339}, - publisher = {IEEE Computer Society}, - address = {Washington, DC, USA}, - keywords = {all pairs shortest paths, subcubic algorithms, equivalences, reductions, matrix multiplication, triangle detection, minimum cycle, replacement paths}, -} - -@inproceedings{Kroni:2013:PGA:2489837.2489844, - author = {Kr\"{o}ni, Daniel and Schweizer, Raphael}, - title = {Parsing Graphs: Applying Parser Combinators to Graph Traversals}, - booktitle = {Proceedings of the 4th Workshop on Scala}, - series = {SCALA '13}, - year = {2013}, - isbn = {978-1-4503-2064-1}, - location = {Montpellier, France}, - pages = {7:1--7:4}, - articleno = {7}, - numpages = {4}, - url = {http://doi.acm.org/10.1145/2489837.2489844}, - doi = {10.1145/2489837.2489844}, - acmid = {2489844}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {Scala, domain specific language, graph database, graph traversal, parser combinators}, -} - -@inproceedings{Reps, - author = {Reps, Thomas}, - title = {Program Analysis via Graph Reachability}, - booktitle = {Proceedings of the 1997 International Symposium on Logic Programming}, - series = {ILPS '97}, - year = {1997}, - isbn = {0-262-63180-6}, - location = {Port Washington, New York, USA}, - pages = {5--19}, - numpages = {15}, - url = {http://dl.acm.org/citation.cfm?id=271338.271343}, - acmid = {271343}, - publisher = {MIT Press}, - address = {Cambridge, MA, USA}, -} - -@inproceedings{LabelFlowCFLReachability, - title={Existential label flow inference via CFL reachability}, - author={Pratikakis, Polyvios and Foster, Jeffrey S and Hicks, Michael}, - booktitle={SAS}, - volume={6}, - pages={88--106}, - year={2006}, - organization={Springer} -} - -@inproceedings{Yannakakis, - title={Graph-theoretic methods in database theory}, - author={Yannakakis, Mihalis}, - booktitle={Proceedings of the ninth ACM SIGACT-SIGMOD-SIGART symposium on Principles of database systems}, - pages={230--242}, - year={1990}, - organization={ACM} -} - -@inproceedings{specificationCFLReachability, - title={Specification inference using context-free language reachability}, - author={Bastani, Osbert and Anand, Saswat and Aiken, Alex}, - booktitle={ACM SIGPLAN Notices}, - volume={50}, - number={1}, - pages={553--566}, - year={2015}, - organization={ACM} -} - -@inproceedings{Zheng, - author = {Zheng, Xin and Rugina, Radu}, - title = {Demand-driven Alias Analysis for C}, - booktitle = {Proceedings of the 35th Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages}, - series = {POPL '08}, - year = {2008}, - isbn = {978-1-59593-689-9}, - location = {San Francisco, California, USA}, - pages = {197--208}, - numpages = {12}, - url = {http://doi.acm.org/10.1145/1328438.1328464}, - doi = {10.1145/1328438.1328464}, - acmid = {1328464}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {CFL reachability, alias analysis, demand-driven analysis, memory disambiguation, pointer analysis}, -} - -@inproceedings{Nole:2016:RPQ:2949689.2949711, - author = {Nol{\'e}, Maurizio and Sartiani, Carlo}, - title = {Regular Path Queries on Massive Graphs}, - booktitle = {Proceedings of the 28th International Conference on Scientific and Statistical Database Management}, - series = {SSDBM '16}, - year = {2016}, - isbn = {978-1-4503-4215-5}, - location = {Budapest, Hungary}, - pages = {13:1--13:12}, - articleno = {13}, - numpages = {12}, - url = {http://doi.acm.org/10.1145/2949689.2949711}, - doi = {10.1145/2949689.2949711}, - acmid = {2949711}, - publisher = {ACM}, - address = {New York, NY, USA}, -} - -@article{DBLP:journals/corr/abs-1010-5023, - author = {Matthew Might and - David Darais}, - title = {Yacc is dead}, - journal = {CoRR}, - volume = {abs/1010.5023}, - year = {2010}, - url = {http://arxiv.org/abs/1010.5023}, - archivePrefix = {arXiv}, - eprint = {1010.5023}, - timestamp = {Mon, 13 Aug 2018 16:46:08 +0200}, - biburl = {https://dblp.org/rec/bib/journals/corr/abs-1010-5023}, - bibsource = {dblp computer science bibliography, https://dblp.org} -} - -@inproceedings{Adams:2016:CPP:2908080.2908128, - author = {Adams, Michael D. and Hollenbeck, Celeste and Might, Matthew}, - title = {On the Complexity and Performance of Parsing with Derivatives}, - booktitle = {Proceedings of the 37th ACM SIGPLAN Conference on Programming Language Design and Implementation}, - series = {PLDI '16}, - year = {2016}, - isbn = {978-1-4503-4261-2}, - location = {Santa Barbara, CA, USA}, - pages = {224--236}, - numpages = {13}, - url = {http://doi.acm.org/10.1145/2908080.2908128}, - doi = {10.1145/2908080.2908128}, - acmid = {2908128}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {Parsing, Parsing with derivatives, Performance}, -} - -@article{Might:2011:PDF:2034574.2034801, - author = {Might, Matthew and Darais, David and Spiewak, Daniel}, - title = {Parsing with Derivatives: A Functional Pearl}, - journal = {SIGPLAN Not.}, - issue_date = {September 2011}, - volume = {46}, - number = {9}, - month = sep, - year = {2011}, - issn = {0362-1340}, - pages = {189--195}, - numpages = {7}, - url = {http://doi.acm.org/10.1145/2034574.2034801}, - doi = {10.1145/2034574.2034801}, - acmid = {2034801}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {context-free grammar, derivative, formal languages, parser combinator, parsing, regular expressions}, -} - -@article{andersenparsing, - title={Parsing With Derivatives}, - author={Andersen, Leif} -} - -@phdthesis{SPPF, - title={Parser generation for interactive environments}, - author={Rekers, Joan Gerard}, - year={1992}, - school={Universiteit van Amsterdam} -} - -@article{Scott:2006:RNG:1146809.1146810, - author = {Scott, Elizabeth and Johnstone, Adrian}, - title = {Right Nulled GLR Parsers}, - journal = {ACM Trans. Program. Lang. Syst.}, - issue_date = {July 2006}, - volume = {28}, - number = {4}, - month = jul, - year = {2006}, - issn = {0164-0925}, - pages = {577--618}, - numpages = {42}, - url = {http://doi.acm.org/10.1145/1146809.1146810}, - doi = {10.1145/1146809.1146810}, - acmid = {1146810}, - publisher = {ACM}, - address = {New York, NY, USA}, - keywords = {General context-free grammars, generalized LR parsing}, -} - -@InProceedings{10.1007/978-3-662-46663-6_5, -author="Afroozeh, Ali -and Izmaylova, Anastasia", -editor="Franke, Bj{\"o}rn", -title="Faster, Practical GLL Parsing", -booktitle="Compiler Construction", -year="2015", -publisher="Springer Berlin Heidelberg", -address="Berlin, Heidelberg", -pages="89--108", -abstract="Generalized LL (GLL) parsing is an extension of recursivedescent (RD) parsing that supports all context-free grammars in cubic time and space. GLL parsers have the direct relationship with the grammar that RD parsers have, and therefore, compared to GLR, are easier to understand, debug, and extend. This makes GLL parsing attractive for parsing programming languages.", -isbn="978-3-662-46663-6" -} - -@article{Scott:2007:BCT:1289813.1289815, - author = {Scott, Elizabeth and Johnstone, Adrian and Economopoulos, Rob}, - title = {BRNGLR: A Cubic Tomita-style GLR Parsing Algorithm}, - journal = {Acta Inf.}, - issue_date = {September 2007}, - volume = {44}, - number = {6}, - month = sep, - year = {2007}, - issn = {0001-5903}, - pages = {427--461}, - numpages = {35}, - url = {http://dx.doi.org/10.1007/s00236-007-0054-z}, - doi = {10.1007/s00236-007-0054-z}, - acmid = {1289815}, - publisher = {Springer-Verlag New York, Inc.}, - address = {Secaucus, NJ, USA}, -} - -@inproceedings{Billot:1989:SSF:981623.981641, - author = {Billot, Sylvie and Lang, Bernard}, - title = {The Structure of Shared Forests in Ambiguous Parsing}, - booktitle = {Proceedings of the 27th Annual Meeting on Association for Computational Linguistics}, - series = {ACL '89}, - year = {1989}, - location = {Vancouver, British Columbia, Canada}, - pages = {143--151}, - numpages = {9}, - url = {https://doi.org/10.3115/981623.981641}, - doi = {10.3115/981623.981641}, - acmid = {981641}, - publisher = {Association for Computational Linguistics}, - address = {Stroudsburg, PA, USA}, - keywords = {Ambiguity, Chart Parsing, Context-Free Parsing, Dynamic Programming, Earley Parsing, Parse Forest, Parse Tree, Parsing Schemata, Parsing Strategies}, -} - -@article{Scott:2010:GP:1860132.1860320, - author = {Scott, Elizabeth and Johnstone, Adrian}, - title = {GLL Parsing}, - journal = {Electron. Notes Theor. Comput. Sci.}, - issue_date = {September, 2010}, - volume = {253}, - number = {7}, - month = sep, - year = {2010}, - issn = {1571-0661}, - pages = {177--189}, - numpages = {13}, - url = {http://dx.doi.org/10.1016/j.entcs.2010.08.041}, - doi = {10.1016/j.entcs.2010.08.041}, - acmid = {1860320}, - publisher = {Elsevier Science Publishers B. V.}, - address = {Amsterdam, The Netherlands, The Netherlands}, - keywords = {RNGLR and RIGLR parsing, context free languages, generalised parsing, recursive descent}, -} - -@article{Okhotin:2014:PMM:2565359.2565379, - author = {Okhotin, Alexander}, - title = {Parsing by Matrix Multiplication Generalized to Boolean Grammars}, - journal = {Theor. Comput. Sci.}, - issue_date = {January, 2014}, - volume = {516}, - month = jan, - year = {2014}, - issn = {0304-3975}, - pages = {101--120}, - numpages = {20}, - url = {http://dx.doi.org/10.1016/j.tcs.2013.09.011}, - doi = {10.1016/j.tcs.2013.09.011}, - acmid = {2565379}, - publisher = {Elsevier Science Publishers Ltd.}, - address = {Essex, UK}, - keywords = {Boolean grammars, Conjunctive grammars, Context-free grammars, Matrix multiplication, Parsing}, -} - -@inproceedings{Okhotin:2003:BG:1758089.1758123, - author = {Okhotin, Alexander}, - title = {Boolean Grammars}, - booktitle = {Proceedings of the 7th International Conference on Developments in Language Theory}, - series = {DLT'03}, - year = {2003}, - isbn = {3-540-40434-1}, - location = {Szeged, Hungary}, - pages = {398--410}, - numpages = {13}, - url = {http://dl.acm.org/citation.cfm?id=1758089.1758123}, - acmid = {1758123}, - publisher = {Springer-Verlag}, - address = {Berlin, Heidelberg}, -} - -@article{OKHOTIN2014101, -title = "Parsing by matrix multiplication generalized to Boolean grammars", -journal = "Theoretical Computer Science", -volume = "516", -pages = "101 - 120", -year = "2014", -issn = "0304-3975", -doi = "https://doi.org/10.1016/j.tcs.2013.09.011", -url = "http://www.sciencedirect.com/science/article/pii/S0304397513006919", -author = "Alexander Okhotin", -keywords = "Boolean grammars, Conjunctive grammars, Context-free grammars, Matrix multiplication, Parsing", -abstract = "The well-known parsing algorithm for context-free grammars due to Valiant (1975) [25] is analyzed and extended to handle the more general Boolean grammars, which are context-free grammars augmented with conjunction and negation operators in the rules. The algorithm reduces construction of a parsing table to computing multiple products of Boolean matrices of various sizes. Its time complexity on an input string of length n is O(BMM(n)logn), where BMM(n) is the number of operations needed to multiply two Boolean matrices of size n×n, which is O(nω) with ω<2.373 as per the current knowledge. A parse tree can be constructed in time MM(n)logO(1)n (where MM(n) is the complexity of multiplying two integer matrices), by applying a known efficient procedure for determining witnesses for Boolean matrix multiplication. The algorithm has a succinct proof of correctness and is ready to be implemented." -} - -@article{f60a33d409364914be560cac0e54b12c, -title = "Conjunctive and boolean grammars: The true general case of the context-free grammars", -abstract = "Conjunctive grammars extend the definition of a context-free grammar by allowing a conjunction operation in the rules; Boolean grammars are further equipped with an explicit negation. These grammars maintain the main principle of the context-free grammars, that of defining syntactically correct strings inductively from their substrings, but lift the restriction of using disjunction only. This paper surveys the results on conjunctive and Boolean grammars obtained over the last decade, comparing them to the corresponding results for ordinary context-free grammars and their main subfamilies. Much attention is given to parsing algorithms, most of which are inherited from the case of ordinary context-free grammars without increasing their computational complexity. The intended readership includes any computer scientists looking for a compact and accessible description of this formal model and its properties, as well as for a general outlook on formal grammars. The paper is also addressed to theoretical computer scientists seeking a subject for research; an account of pure theoretical research in the area presented in this paper is accompanied by a list of significant open problems, with an award offered for the first correct solution of each problem. Several directions for future investigation are proposed.", -keywords = "Boolean grammars, Conjunctive grammars, Context-free grammars, Formal languages, Language equations, Parsing", -author = "Alexander Okhotin", -year = "2013", -month = "8", -day = "1", -doi = "10.1016/j.cosrev.2013.06.001", -language = "English", -volume = "9", -pages = "27--59", -journal = "Computer Science Review", -issn = "1574-0137", -publisher = "Elsevier", -} - -@article{565CECD7E8F5C6063935B41DB41797AA37D53B04, -author = {Azimov, Rustam and Grigorev, Semyon}, -year = {2018}, -month = {01}, -pages = {149-166}, -title = {Path querying using conjunctive grammars}, -volume = {30}, -journal = {Proceedings of the Institute for System Programming of the RAS}, -doi = {10.15514/ISPRAS-2018-30(2)-8} -} - -@InProceedings{10.1007/978-3-319-46523-4_38, -author="Zhang, Xiaowang -and Feng, Zhiyong -and Wang, Xin -and Rao, Guozheng -and Wu, Wenrui", -editor="Groth, Paul -and Simperl, Elena -and Gray, Alasdair -and Sabou, Marta -and Kr{\"o}tzsch, Markus -and Lecue, Freddy -and Fl{\"o}ck, Fabian -and Gil, Yolanda", -title="Context-Free Path Queries on RDF Graphs", -booktitle="The Semantic Web -- ISWC 2016", -year="2016", -publisher="Springer International Publishing", -address="Cham", -pages="632--648", -abstract="Navigational graph queries are an important class of queries that can extract implicit binary relations over the nodes of input graphs. Most of the navigational query languages used in the RDF community, e.g. property paths in W3C SPARQL 1.1 and nested regular expressions in nSPARQL, are based on the regular expressions. It is known that regular expressions have limited expressivity; for instance, some natural queries, like same generation-queries, are not expressible with regular expressions. To overcome this limitation, in this paper, we present cfSPARQL, an extension of SPARQL query language equipped with context-free grammars. The cfSPARQL language is strictly more expressive than property paths and nested expressions. The additional expressivity can be used for modelling graph similarities, graph summarization and ontology alignment. Despite the increasing expressivity, we show that cfSPARQL still enjoys a low computational complexity and can be evaluated efficiently.", -isbn="978-3-319-46523-4" -} - -@inproceedings{hellingsRelational, - title={Conjunctive context-free path queries}, - author={Hellings, Jelle}, - booktitle={Proceedings of ICDT'14}, - pages={119--130}, - year={2014} -} - -@misc{hellings2015querying, - title={Querying for Paths in Graphs using Context-Free Path Queries}, - author={Jelle Hellings}, - year={2015}, - eprint={1502.02242}, - archivePrefix={arXiv}, - primaryClass={cs.DB} -} - -@article{Hellings2015PathRF, - title={Path Results for Context-free Grammar Queries on Graphs}, - author={Jelle Hellings}, - journal={ArXiv}, - year={2015}, - volume={abs/1502.02242} -} - -@inproceedings{bradford2007quickest, - title={Quickest path distances on context-free labeled graphs}, - author={Bradford, Phillip G}, - booktitle={Appear in 6-th WSEAS Conference on Computational Intelligence, Man-Machine Systems and Cybernetics}, - year={2007}, - organization={Citeseer} -} - -@inproceedings{ward2008distributed, - title={A distributed context-free language constrained shortest path algorithm}, - author={Ward, Charles B and Wiegand, Nathan M and Bradford, Phillip G}, - booktitle={2008 37th International Conference on Parallel Processing}, - pages={373--380}, - year={2008}, - organization={IEEE} -} - -@inproceedings{bradford2016fast, - title={Fast point-to-point Dyck constrained shortest paths on a DAG}, - author={Bradford, Phillip G and Choppella, Venkatesh}, - booktitle={2016 IEEE 7th Annual Ubiquitous Computing, Electronics \& Mobile Communication Conference (UEMCON)}, - pages={1--7}, - year={2016}, - organization={IEEE} -} - -@inproceedings{Bradford:2008:LCG:1373936.1373946, - author = {Bradford, Phillip G.}, - title = {Language Constrained Graph Problems: A Microcosm of Engineering Research and Development}, - booktitle = {Proceedings of the 2Nd WSEAS International Conference on Computer Engineering and Applications}, - series = {CEA'08}, - year = {2008}, - isbn = {978-960-6766-33-6}, - location = {Acapulco, Mexico}, - pages = {71--76}, - numpages = {6}, - url = {http://dl.acm.org/citation.cfm?id=1373936.1373946}, - acmid = {1373946}, - publisher = {World Scientific and Engineering Academy and Society (WSEAS)}, - address = {Stevens Point, Wisconsin, USA}, - keywords = {creative destruction, entrepreneurship, integrated learning base, intellectual infrastructure, labeled graphs, paradigm shift, path problems, science and business}, -} - - -@article{doi:10.1137/S0097539798337716, -author = {Barrett, C. and Jacob, R. and Marathe, M.}, -title = {Formal-Language-Constrained Path Problems}, -journal = {SIAM Journal on Computing}, -volume = {30}, -number = {3}, -pages = {809-837}, -year = {2000}, -doi = {10.1137/S0097539798337716}, -URL = {https://doi.org/10.1137/S0097539798337716}, -eprint = { https://doi.org/10.1137/S0097539798337716} -} - -@article{barrett2007label, - title={Label constrained shortest path algorithms: An experimental evaluation using transportation networks}, - author={Barrett, Chris and Bisset, Keith and Holzer, Martin and Konjevod, Goran and Marathe, Madhav and Wagner, Dorothea}, - journal={March}, - volume={9}, - pages={2007}, - year={2007} -} - -@article{Ward:2010:CRL:1710158.1710234, - author = {Ward, Charles B. and Wiegand, Nathan M.}, - title = {Complexity Results on Labeled Shortest Path Problems from Wireless Routing Metrics}, - journal = {Comput. Netw.}, - issue_date = {February, 2010}, - volume = {54}, - number = {2}, - month = feb, - year = {2010}, - issn = {1389-1286}, - pages = {208--217}, - numpages = {10}, - url = {http://dx.doi.org/10.1016/j.comnet.2009.04.012}, - doi = {10.1016/j.comnet.2009.04.012}, - acmid = {1710234}, - publisher = {Elsevier North-Holland, Inc.}, - address = {New York, NY, USA}, - keywords = {Approximation algorithms, Labeled paths, Shortest paths, Wireless routing metrics}, -} - -@inproceedings{kupferman2016eulerian, - title={Eulerian paths with regular constraints}, - author={Kupferman, Orna and Vardi, Gal}, - booktitle={41st International Symposium on Mathematical Foundations of Computer Science (MFCS 2016)}, - year={2016}, - organization={Schloss Dagstuhl-Leibniz-Zentrum fuer Informatik} -} - -@InProceedings{10.1007/978-3-642-22321-1_24, -author="Holzer, Markus -and Kutrib, Martin -and Leiter, Ursula", -editor="Mauri, Giancarlo -and Leporati, Alberto", -title="Nodes Connected by Path Languages", -booktitle="Developments in Language Theory", -year="2011", -publisher="Springer Berlin Heidelberg", -address="Berlin, Heidelberg", -pages="276--287", -abstract="We investigate reachability problems on different types of labeled graphs constrained to formal languages from a family {\$}{\backslash}mathcal{\{}L{\}}{\$}. If every language in {\$}{\backslash}mathcal{\{}L{\}}{\$}is accepted by a one-way nondeterministic storage automaton, then we give an appealing characterization of the computational complexity of the labeled graph reachability problem in terms of two-way nondeterministic storage automata with auxiliary worktape that is logarithmic-space bounded. Moreover, we also consider acyclic graphs in the underlying reachability instance, obtaining a lower bound result for auxiliary storage automata that are simultaneously space and time restricted.", -isbn="978-3-642-22321-1" -} - -@inproceedings{axelsson2011formal, - title={Formal language constrained reachability and model checking propositional dynamic logics}, - author={Axelsson, Roland and Lange, Martin}, - booktitle={International Workshop on Reachability Problems}, - pages={45--57}, - year={2011}, - organization={Springer} -} - -@phdthesis{DBLP:phd/ethos/Economopoulos06, - author = {Giorgios Rob Economopoulos}, - title = {Generalised {LR} parsing algorithms}, - school = {Royal Holloway, University of London, {UK}}, - year = {2006}, - url = {http://ethos.bl.uk/OrderDetails.do?uin=uk.bl.ethos.435358}, - timestamp = {Mon, 05 Sep 2016 19:00:20 +0200}, - biburl = {https://dblp.org/rec/bib/phd/ethos/Economopoulos06}, - bibsource = {dblp computer science bibliography, https://dblp.org} -} - -@article{DBLP:journals/jalc/Okhotin01, - author = {Alexander Okhotin}, - title = {Conjunctive Grammars}, - journal = {Journal of Automata, Languages and Combinatorics}, - volume = {6}, - number = {4}, - pages = {519--535}, - year = {2001}, - url = {https://doi.org/10.25596/jalc-2001-519}, - doi = {10.25596/jalc-2001-519}, - timestamp = {Thu, 15 Nov 2018 14:56:53 +0100}, - biburl = {https://dblp.org/rec/bib/journals/jalc/Okhotin01}, - bibsource = {dblp computer science bibliography, https://dblp.org} -} - -@article{Okhotin2002, - author="Okhotin, A. S.", - title="Conjunctive Grammars and Systems of Language Equations", - journal="Programming and Computer Software", - year="2002", - month="Sep", - day="01", - volume="28", - number="5", - pages="243--249", - abstract="This paper studies systems of language equations that are resolved with respect to variables and contain the operations of concatenation, union and intersection. Every system of this kind is proved to have a least fixed point, and the equivalence of these systems to conjunctive grammars is established. This allows us to obtain an algebraic characterization of the language family generated by conjunctive grammars.", - issn="1608-3261", - doi="10.1023/A:1020213411126", - url="https://doi.org/10.1023/A:1020213411126" -} - - -@article{DBLP:journals/tcs/Okhotin03a, - author = {Alexander Okhotin}, - title = {On the closure properties of linear conjunctive languages}, - journal = {Theor. Comput. Sci.}, - volume = {299}, - number = {1-3}, - pages = {663--685}, - year = {2003}, - url = {https://doi.org/10.1016/S0304-3975(02)00543-1}, - doi = {10.1016/S0304-3975(02)00543-1}, - timestamp = {Wed, 14 Jun 2017 20:32:07 +0200}, - biburl = {https://dblp.org/rec/bib/journals/tcs/Okhotin03a}, - bibsource = {dblp computer science bibliography, https://dblp.org} -} - -@article{SEKI1991191, - title = "On multiple context-free grammars", - journal = "Theoretical Computer Science", - volume = "88", - number = "2", - pages = "191 - 229", - year = "1991", - issn = "0304-3975", - doi = "https://doi.org/10.1016/0304-3975(91)90374-B", - url = "http://www.sciencedirect.com/science/article/pii/030439759190374B", - author = "Hiroyuki Seki and Takashi Matsumura and Mamoru Fujii and Tadao Kasami", - abstract = "Multiple context-free grammars (mcfg's) is a subclass of generalized context-free grammars introduced by Pollard (1984) in order to describe the syntax of natural languages. The class of languages generated by mcfg's (called multiple context-free languages or, shortly, mcfl's) properly includes the class of context-free languages and is properly included in the class of context-sensitive languages. First, the paper presents results on the generative capacity of mcfg's and also on the properties of mcfl's such as formal language-theoretic closure properties. Next, it is shown that the time complexity of the membership problem for multiple context-free languages is O(ne), where n is the length of an input string and e is a constant called the degree of a given mcfg. Head grammars (hg's) introduced by Pollard and tree adjoining grammars (tag's) introduced by Joshi et al. (1975) are also grammatical formalisms to describe the syntax of natural languages. The paper also presents the following results on the generative capacities of hg's, tag's and 2-mcfg's, which are a subclass of mcfg's: (1) The class HL of languages generated by hg's is the same as the one generated by tag's; (2) HL is the same as the one generated by left-wrapping hg's (or right-wrapping hg's) which is a proper subclass of hg's; (3) HL is properly included in the one generated by 2-mcfg's. As a corollary of (1), it is also shown that HL is a substitution-closed full AFL." -} - -@Inbook{Joshi1997, - author="Joshi, Aravind K. - and Schabes, Yves", - editor="Rozenberg, Grzegorz - and Salomaa, Arto", - title="Tree-Adjoining Grammars", - bookTitle="Handbook of Formal Languages: Volume 3 Beyond Words", - year="1997", - publisher="Springer Berlin Heidelberg", - address="Berlin, Heidelberg", - pages="69--123", - abstract="In this paper, we will describe a tree generating system called tree-adjoining grammar (TAG) and state some of the recent results about TAGs. The work on TAGs is motivated by linguistic considerations. However, a number of formal results have been established for TAGs, which we believe, would be of interest to researchers in formal languages and automata, including those interested in tree grammars and tree automata.", - isbn="978-3-642-59126-6", - doi="10.1007/978-3-642-59126-6_2", - url="https://doi.org/10.1007/978-3-642-59126-6_2" -} - -@article{cfpqBio, - author = {Sevon, Petteri and Eronen, Lauri}, - year = {2008}, - month = {06}, - pages = {}, - title = {Subgraph Queries by Context-free Grammars}, - volume = {5}, - journal = {Journal of Integrative Bioinformatics}, - doi = {10.1515/jib-2008-100} -} - -@article { Floyd1962, - title={Algorithm 97: shortest path}, - author={Floyd, Robert W}, - journal={Communications of the ACM}, - volume={5}, - number={6}, - pages={345}, - year={1962}, - publisher={ACM} -} - -@article { Bernard1959, - title={Transitivit{\'e} et connexit{\'e}}, - author={Roy, Bernard}, - journal={Comptes Rendus Hebdomadaires Des Seances De L Academie Des Sciences}, - volume={249}, - number={2}, - pages={216--218}, - year={1959}, - publisher={GAUTHIER-VILLARS/EDITIONS ELSEVIER 23 RUE LINOIS, 75015 PARIS, FRANCE} -} - -@article { Warshall1962, - title={A theorem on boolean matrices}, - author={Warshall, Stephen}, - booktitle={Journal of the ACM}, - year={1962}, - organization={Citeseer} -} - -@article{ FredmanAPSP1976, - title={New bounds on the complexity of the shortest path problem}, - author={Fredman, Michael L}, - journal={SIAM Journal on Computing}, - volume={5}, - number={1}, - pages={83--89}, - year={1976}, - publisher={SIAM} -} - -@article { Dobosiewicz1990, - title={A more efficient algorithm for the min-plus multiplication}, - author={Dobosiewicz, Wlodzimierz}, - journal={International journal of computer mathematics}, - volume={32}, - number={1-2}, - pages={49--60}, - year={1990}, - publisher={Taylor \& Francis} -} - -@article { Takaoka1992, - title={A new upper bound on the complexity of the all pairs shortest path problem}, - author={Takaoka, Tadao}, - journal={Information Processing Letters}, - volume={43}, - number={4}, - pages={195--199}, - year={1992}, - publisher={Elsevier} -} - -@inproceedings { Takaoka2004, - author = {Takaoka, T.}, - title = {A faster algorithm for the all-pairs shortest path problem and its application}, - booktitle = {Computing and Combinatorics}, - booktitleaddon = {10th international conference}, - year = {2004}, - volume = {3106}, - pages = {278--289} -} - -@article {Takaoka2005, - author = {Takaoka, T.}, - title = {An $O(n^3 \log \log n/ \log n)$ time algorithm for the all-pairs shortest path problem}, - year = {2005}, - journal = {Information Processing Letters}, - volume = {96}, - pages = {155--161} -} - -@article { Han2004, - title={Improved algorithm for all pairs shortest paths}, - author={Han, Yijie}, - journal={Information Processing Letters}, - volume={91}, - number={5}, - pages={245--250}, - year={2004}, - publisher={Elsevier} -} - -@inproceedings { Zwick2004, - title={A slightly improved sub-cubic algorithm for the all pairs shortest paths problem with real edge lengths}, - author={Zwick, Uri}, - booktitle={International Symposium on Algorithms and Computation}, - pages={921--932}, - year={2004}, - organization={Springer} -} - -@inproceedings { Lavallee2004, - title={An Efficient APSP Algorithm.}, - author={Lavall{\'e}e, Ivan and Bui, Marc and Quoc, Trung Ha}, - booktitle={RIVF}, - pages={211--214}, - year={2004} -} - -@article { Seidel1995, - title={On the all-pairs-shortest-path problem in unweighted undirected graphs}, - author={Seidel, Raimund}, - journal={Journal of computer and system sciences}, - volume={51}, - number={3}, - pages={400--403}, - year={1995}, - publisher={Elsevier} -} - -@article{ Strassen1969, - title={Gaussian elimination is not optimal}, - author={Strassen, Volker}, - journal={Numerische mathematik}, - volume={13}, - number={4}, - pages={354--356}, - year={1969}, - publisher={Springer} -} - -@inproceedings { Pan1978, - title={Strassen's algorithm is not optimal trilinear technique of aggregating, uniting and canceling for constructing fast algorithms for matrix operations}, - author={Pan, V. Ya.}, - booktitle={19th Annual Symposium on Foundations of Computer Science (sfcs 1978)}, - pages={166--176}, - year={1978}, - organization={IEEE}} -} - -@article{ BiniCapoRoma1979, - author={Bini, Dario Andrea and Capovani, Milvio and Romani, Francesco and Lotti, Grazia}, - title = {$O(n^{2.7799})$ complexity for approximate matrix multiplication}, - year = {1979}, - journal = {Information Processing Letters}, - volume = {8(5)}, - pages = {234--235} -} - -@article{ Schonhage1981, - title={Partial and total matrix multiplication}, - author={Sch{\"o}nhage, Arnold}, - journal={SIAM Journal on Computing}, - volume={10}, - number={3}, - pages={434--455}, - year={1981}, - publisher={SIAM} -} - -@article{ CoppWino1982, - title={On the asymptotic complexity of matrix multiplication}, - author={Coppersmith, Don and Winograd, Shmuel}, - journal={SIAM Journal on Computing}, - volume={11}, - number={3}, - pages={472--492}, - year={1982}, - publisher={SIAM} -} - -@article{ CoppWino1990, - title={Matrix multiplication via arithmetic progressions}, - author={Coppersmith, Don and Winograd, Shmuel}, - journal={Journal of symbolic computation}, - volume={9}, - number={3}, - pages={251--280}, - year={1990}, - publisher={Academic Press} -} - -@article{Chan2010, - title={More algorithms for all-pairs shortest paths in weighted graphs}, - author={Chan, Timothy M}, - journal={SIAM Journal on Computing}, - volume={39}, - number={5}, - pages={2075--2089}, - year={2010}, - publisher={SIAM} -} - -@article{Wirth1977, - title={What can we do about the unnecessary diversity of notation for syntactic definitions?}, - author={Wirth, Niklaus}, - journal={Communications of the ACM}, - volume={20}, - number={11}, - pages={822--823}, - year={1977}, - publisher={ACM} -} - -@article{Hemerik2009, - title={Towards a Taxonomy for ECFG and RRPG Parsing}, - author={Hemerik, Kees}, - journal={Proceedings of the 3rd International Conference on Language and Automata Theory and Applications}, - pages={410--421}, - year={2009}, - publisher={LATA} -} -@inproceedings{tomita1988graph, - title = "Graph-structured Stack and Natural Language Parsing", - author = "Tomita, Masaru", - booktitle = "26th Annual Meeting of the Association for Computational Linguistics", - month = jun, - year = "1988", - address = "Buffalo, New York, USA", - publisher = "Association for Computational Linguistics", - url = "https://www.aclweb.org/anthology/P88-1031", - doi = "10.3115/982023.982054", - pages = "249--257", -} - -@article{tomita-1987-efficient, - title = "An Efficient Augmented-Context-Free Parsing Algorithm", - author = "Tomita, Masaru", - journal = "Computational Linguistics", - volume = "13", - year = "1987", - url = "https://www.aclweb.org/anthology/J87-1004", - pages = "31--46", -} - -@article{Brzozowski1964, - title = {Derivatives of Regular Expressions}, - author = {Brzozowski, Janusz A.}, - journal = {Journal of the ACM}, - volume = {11 (4)}, - year = {1964}, - pages = {481–-494}, - doi = {10.1145/321239.321249} -} - -@online{Earley, - author = {{Sylvain Salvati}}, - title = {Multiple Context-free Grammars}, - url = {https://www.labri.fr/perso/salvati/downloads/cours/esslli/course2.pdf}, - organization = {NRIA Bordeaux Sud-Ouest}, - date = {2016-02-02}, - urldate = {2019-12-25} -} - -@article {Datalog, - author = {G. Gottlob and S. Ceri and L. Tanca}, - journal = {IEEE Transactions on Knowledge \& Data Engineering}, - title = {What You Always Wanted to Know About Datalog (And Never Dared to Ask)}, - year = {1989}, - volume = {1}, - number = {01}, - issn = {1558-2191}, - pages = {146-166}, - keywords = {optimisation methods; datalog; database query language; logic programming; syntax; semantics; relational database; logic programming; query languages; relational databases}, - doi = {10.1109/69.43410}, - publisher = {IEEE Computer Society}, - address = {Los Alamitos, CA, USA}, - month = {jan} -} - -@inproceedings{Magic, - author = {Bancilhon, Francois and Maier, David and Sagiv, Yehoshua and Ullman, Jeffrey D}, - title = {Magic Sets and Other Strange Ways to Implement Logic Programs (Extended Abstract)}, - booktitle = {Proceedings of the Fifth ACM SIGACT-SIGMOD Symposium on Principles of Database Systems}, - series = {PODS '86}, - year = {1986}, - isbn = {0-89791-179-2}, - location = {Cambridge, Massachusetts, USA}, - pages = {1--15}, - numpages = {15}, - url = {http://doi.acm.org/10.1145/6012.15399}, - doi = {10.1145/6012.15399}, - acmid = {15399}, - publisher = {ACM}, - address = {New York, NY, USA}, -} - -@article{Dyrka2019, - doi = {10.7717/peerj.6559}, - url = {https://doi.org/10.7717/peerj.6559}, - year = {2019}, - month = mar, - publisher = {{PeerJ}}, - volume = {7}, - pages = {e6559}, - author = {Witold Dyrka and Mateusz Pyzik and Fran{\c{c}}ois Coste and Hugo Talibart}, - title = {Estimating probabilistic context-free grammars for proteins using contact map constraints}, - journal = {{PeerJ}} -} -@article{WJAnderson2012, - doi = {10.1186/1471-2105-13-78}, - url = {https://doi.org/10.1186/1471-2105-13-78}, - year = {2012}, - publisher = {Springer Science and Business Media {LLC}}, - volume = {13}, - number = {1}, - pages = {78}, - author = {James WJ Anderson and Paula Tataru and Joe Staines and Jotun Hein and Rune Lyngs{\o}}, - title = {Evolving stochastic context--free grammars for {RNA} secondary structure prediction}, - journal = {{BMC} Bioinformatics} -} - -@article{zier2013rna, - title={RNA pseudoknot prediction through stochastic conjunctive grammars}, - author={Zier-Vogel, Ryan and Domaratzki, Michael}, - journal={Computability in Europe 2013. Informal Proceedings}, - pages={80--89}, - year={2013} -} - -@inproceedings{10.5555/3305381.3305582, -author = {Kusner, Matt J. and Paige, Brooks and Hern\'{a}ndez-Lobato, Jos\'{e} Miguel}, -title = {Grammar Variational Autoencoder}, -year = {2017}, -publisher = {JMLR.org}, -booktitle = {Proceedings of the 34th International Conference on Machine Learning - Volume 70}, -pages = {1945–1954}, -numpages = {10}, -location = {Sydney, NSW, Australia}, -series = {ICML’17} -} - -@inproceedings{kasai-etal-2017-tag, - title = "{TAG} Parsing with Neural Networks and Vector Representations of Supertags", - author = "Kasai, Jungo and - Frank, Bob and - McCoy, Tom and - Rambow, Owen and - Nasr, Alexis", - booktitle = "Proceedings of the 2017 Conference on Empirical Methods in Natural Language Processing", - month = sep, - year = "2017", - address = "Copenhagen, Denmark", - publisher = "Association for Computational Linguistics", - url = "https://www.aclweb.org/anthology/D17-1180", - doi = "10.18653/v1/D17-1180", - pages = "1712--1722", - abstract = "We present supertagging-based models for Tree Adjoining Grammar parsing that use neural network architectures and dense vector representation of supertags (elementary trees) to achieve state-of-the-art performance in unlabeled and labeled attachment scores. The shift-reduce parsing model eschews lexical information entirely, and uses only the 1-best supertags to parse a sentence, providing further support for the claim that supertagging is {``}almost parsing.{''} We demonstrate that the embedding vector representations the parser induces for supertags possess linguistically interpretable structure, supporting analogies between grammatical structures like those familiar from recent work in distributional semantics. This dense representation of supertags overcomes the drawbacks for statistical models of TAG as compared to CCG parsing, raising the possibility that TAG is a viable alternative for NLP tasks that require the assignment of richer structural descriptions to sentences.", -} -@inproceedings{kasai-etal-2018-end, - title = "End-to-End Graph-Based {TAG} Parsing with Neural Networks", - author = "Kasai, Jungo and - Frank, Robert and - Xu, Pauli and - Merrill, William and - Rambow, Owen", - booktitle = "Proceedings of the 2018 Conference of the North {A}merican Chapter of the Association for Computational Linguistics: Human Language Technologies, Volume 1 (Long Papers)", - month = jun, - year = "2018", - address = "New Orleans, Louisiana", - publisher = "Association for Computational Linguistics", - url = "https://www.aclweb.org/anthology/N18-1107", - doi = "10.18653/v1/N18-1107", - pages = "1181--1194", - abstract = "We present a graph-based Tree Adjoining Grammar (TAG) parser that uses BiLSTMs, highway connections, and character-level CNNs. Our best end-to-end parser, which jointly performs supertagging, POS tagging, and parsing, outperforms the previously reported best results by more than 2.2 LAS and UAS points. The graph-based parsing architecture allows for global inference and rich feature representations for TAG parsing, alleviating the fundamental trade-off between transition-based and graph-based parsing systems. We also demonstrate that the proposed parser achieves state-of-the-art performance in the downstream tasks of Parsing Evaluation using Textual Entailments (PETE) and Unbounded Dependency Recovery. This provides further support for the claim that TAG is a viable formalism for problems that require rich structural analysis of sentences.", -} - -@article{10.1145/373243.360208, -author = {Rehof, Jakob and F\"{a}hndrich, Manuel}, -title = {Type-Base Flow Analysis: From Polymorphic Subtyping to CFL-Reachability}, -year = {2001}, -issue_date = {March 2001}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -volume = {36}, -number = {3}, -issn = {0362-1340}, -url = {https://doi.org/10.1145/373243.360208}, -doi = {10.1145/373243.360208}, -journal = {SIGPLAN Not.}, -month = jan, -pages = {54--66}, -numpages = {13} -} - -@inproceedings{10.1145/193173.195287, -author = {Reps, Thomas and Horwitz, Susan and Sagiv, Mooly and Rosay, Genevieve}, -title = {Speeding up Slicing}, -year = {1994}, -isbn = {0897916913}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -url = {https://doi.org/10.1145/193173.195287}, -doi = {10.1145/193173.195287}, -booktitle = {Proceedings of the 2nd ACM SIGSOFT Symposium on Foundations of Software Engineering}, -pages = {11--20}, -numpages = {10}, -keywords = {flow-sensitive summary information, dynamic programming, program slicing, realizable path, program debugging, program dependence graph, dynamic transitive closure}, -location = {New Orleans, Louisiana, USA}, -series = {SIGSOFT '94} -} - -@inproceedings{10.1145/2001420.2001440, -author = {Yan, Dacong and Xu, Guoqing and Rountev, Atanas}, -title = {Demand-Driven Context-Sensitive Alias Analysis for Java}, -year = {2011}, -isbn = {9781450305624}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -url = {https://doi.org/10.1145/2001420.2001440}, -doi = {10.1145/2001420.2001440}, -booktitle = {Proceedings of the 2011 International Symposium on Software Testing and Analysis}, -pages = {155--165}, -numpages = {11}, -keywords = {demand-driven, alias analysis, context sensitivity}, -location = {Toronto, Ontario, Canada}, -series = {ISSTA '11} -} - -@article{10.1145/2714064.2660213, -author = {Zhang, Qirun and Xiao, Xiao and Zhang, Charles and Yuan, Hao and Su, Zhendong}, -title = {Efficient Subcubic Alias Analysis for C}, -year = {2014}, -issue_date = {December 2014}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -volume = {49}, -number = {10}, -issn = {0362-1340}, -url = {https://doi.org/10.1145/2714064.2660213}, -doi = {10.1145/2714064.2660213}, -journal = {SIGPLAN Not.}, -month = oct, -pages = {829--845}, -numpages = {17}, -keywords = {cfl-reachability, alias analysis} -} - -@article{Shemetova2019, - doi = {10.15514/ispras-2019-31(4)-14}, - url = {https://doi.org/10.15514/ispras-2019-31(4)-14}, - year = {2019}, - publisher = {Institute for System Programming of the Russian Academy of Sciences}, - volume = {31}, - number = {4}, - pages = {211--226}, - author = {E.N. Shemetova and S.V. Grigorev}, - title = {Path querying on acyclic graphs using Boolean grammars}, - journal = {Proceedings of the Institute for System Programming of {RAS}} -} - -@article{DBLP:journals/corr/abs-0811-1714, - author = {Martin R. Albrecht and - Gregory V. Bard and - William Hart}, - title = {Efficient Multiplication of Dense Matrices over {GF(2)}}, - journal = {CoRR}, - volume = {abs/0811.1714}, - year = {2008}, - url = {http://arxiv.org/abs/0811.1714}, - archivePrefix = {arXiv}, - eprint = {0811.1714}, - timestamp = {Mon, 13 Aug 2018 16:45:56 +0200}, - biburl = {https://dblp.org/rec/journals/corr/abs-0811-1714.bib}, - bibsource = {dblp computer science bibliography, https://dblp.org} -} - -@MISC{Cusp, - author = "Steven Dalton and Nathan Bell and Luke Olson and Michael Garland", - title = "Cusp: Generic Parallel Algorithms for Sparse Matrix and Graph Computations", - year = "2014", - url = "http://cusplibrary.github.io/", - note = "Version 0.5.0" -} - -@inproceedings{Davis2018Algorithm9S, - title={Algorithm 9xx: SuiteSparse:GraphBLAS: graph algorithms in the language of sparse linear algebra}, - author={Timothy A. Davis}, - year={2018} -} - -@inproceedings{10.1145/3357766.3359532, -author = {Scott, Elizabeth and Johnstone, Adrian}, -title = {Multiple Lexicalisation (a Java Based Study)}, -year = {2019}, -isbn = {9781450369817}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -url = {https://doi.org/10.1145/3357766.3359532}, -doi = {10.1145/3357766.3359532}, -booktitle = {Proceedings of the 12th ACM SIGPLAN International Conference on Software Language Engineering}, -pages = {71–82}, -numpages = {12}, -keywords = {syntax analysis, lexicalisation, generalised parsing}, -location = {Athens, Greece}, -series = {SLE 2019} -} - -@article{BEATTY1980193, -title = "Two iteration theorems for the LL(k) languages", -journal = "Theoretical Computer Science", -volume = "12", -number = "2", -pages = "193 - 228", -year = "1980", -issn = "0304-3975", -doi = "https://doi.org/10.1016/0304-3975(80)90029-8", -url = "http://www.sciencedirect.com/science/article/pii/0304397580900298", -author = "John C. Beatty", -abstract = "The structure of derivation trees over an LL(k) grammar is explored and a property of these trees obtained which is shown to characterize the LL(k) grammars. This characterization, called the LL(k) Left Part Theorem, makes it possible to establish a pair of iteration theorems for the LL(k) languages. These theorems provide a general and powerful method of showing that a language is not LL(k) when that is the case. They thus provide for the first time a flexible tool with which to explore the structure of the LL(k) languages and with which to discriminate between the LL(k) and LR(k) language classes. Examples are given of LR(k) languages which, for various reasons, fail to be LL(k). Easy and rigorous proofs to this effect are given using our LL(k) iteration theorems. In particular, it is proven that the dangling-ELSE construct allowed in PL/I and Pascal cannot be generated by any LL(k) grammar. We also give a new and straightforward proof based on the LL(k) Left Part Theorem that every LL(k) grammar is LR(k)." -} - -@misc{VavilovGroups, - language={russian}, - author = {{\CYRN}иколай Вавилов}, - title = {КОНКРЕТНАЯ ТЕОРИЯ ГРУПП}, - year = {2005}, - url = {http://dobrochan.com/src/pdf/1512/Вавилов-Н.-Конкретная-теория-групп.-Основные-понят.pdf}, - note = {Дата доступа: 29 июня 2021 г.} -} - - -@misc{VavilovRings, - language={russian}, - author = {{\CYRN}иколай Вавилов}, - title = {КОНКРЕТНАЯ ТЕОРИЯ КОЛЕЦ}, - year = {2006}, - url = {http://www.add3d.ru/wp-content/uploads/2019/10/Vavilov-Rings.pdf}, - note = {Дата доступа: 29 июня 2021 г.} -} - -@misc{das2018lower, - title={Lower bounds for Combinatorial Algorithms for Boolean Matrix Multiplication}, - author={Debarati Das and Michal Koucký and Michael Saks}, - year={2018}, - eprint={1801.05202}, - archivePrefix={arXiv}, - primaryClass={cs.CC} -} - -@misc{alman2020refined, - title={A Refined Laser Method and Faster Matrix Multiplication}, - author={Josh Alman and Virginia Vassilevska Williams}, - year={2020}, - eprint={2010.05846}, - archivePrefix={arXiv}, - primaryClass={cs.DS} -} - -@INPROCEEDINGS{5438580, - author={Bansal, Nikhil and Williams, Ryan}, - booktitle={2009 50th Annual IEEE Symposium on Foundations of Computer Science}, - title={Regularity Lemmas and Combinatorial Algorithms}, - year={2009}, - volume={}, - number={}, - pages={745-754}, - doi={10.1109/FOCS.2009.76}} - -@InProceedings{10.1007/978-3-662-47672-7_89, -author="Yu, Huacheng", -editor="Halld{\'o}rsson, Magn{\'u}s M. -and Iwama, Kazuo -and Kobayashi, Naoki -and Speckmann, Bettina", -title="An Improved Combinatorial Algorithm for Boolean Matrix Multiplication", -booktitle="Automata, Languages, and Programming", -year="2015", -publisher="Springer Berlin Heidelberg", -address="Berlin, Heidelberg", -pages="1094--1105", -abstract="We present a new combinatorial algorithm for triangle finding and Boolean matrix multiplication that runs in {\$}{\$}{\backslash}hat{\{}O{\}}(n^3/{\backslash}log ^4 n){\$}{\$}O^(n3/log4n)time, where the {\$}{\$}{\backslash}hat{\{}O{\}}{\$}{\$}O^notation suppresses poly(loglog) factors. This improves the previous best combinatorial algorithm by Chan [4] that runs in {\$}{\$}{\backslash}hat{\{}O{\}}(n^3/{\backslash}log ^3 n){\$}{\$}O^(n3/log3n)time. Our algorithm generalizes the divide-and-conquer strategy of Chan's algorithm.", -isbn="978-3-662-47672-7" -} - - -@article{ArlDinKro70, -author = {{\CYRV}. Арлазаров and {\CYRE}. Диниц and {\CYRM}. Кронрод and {\CYRI}. Фараджев}, -title = {Об экономном построении транзитивного замыкания ориентированного графа}, -journal = {Докл. АН СССР}, -year = {1970}, -volume = {194}, -number = {3}, -pages = {487--488}, -url = {http://mi.mathnet.ru/dan35675} -} - -@book{doi:10.1137/1.9780898719918, -author = {Kepner, Jeremy and Gilbert, John},editor = {Jeremy Kepner and John Gilbert}, -title = {Graph Algorithms in the Language of Linear Algebra}, -publisher = {Society for Industrial and Applied Mathematics}, -year = {2011}, -doi = {10.1137/1.9780898719918}, -address = {}, -edition = {}, -URL = {https://epubs.siam.org/doi/abs/10.1137/1.9780898719918}, -eprint = {https://epubs.siam.org/doi/pdf/10.1137/1.9780898719918} -} -@Misc{tata2007, - author = {H. Comon and M. Dauchet and R. Gilleron and C. L\"oding -and F. Jacquemard -and D. Lugiez and S. Tison and M. Tommasi}, - title = {Tree Automata Techniques and Applications}, - howpublished = {Available on: \url{http://www.grappa.univ-lille3.fr/tata}}, - note = {release October, 12th 2007}, - year = 2007 -} - -@inproceedings{Baras2010PathPI, - title={Path Problems in Networks}, - author={J. Baras and George Theodorakopoulos}, - booktitle={Path Problems in Networks}, - year={2010} -} -@article{EHRIG1992557, -title = {Introduction to graph grammars with applications to semantic networks}, -journal = {Computers \& Mathematics with Applications}, -volume = {23}, -number = {6}, -pages = {557-572}, -year = {1992}, -issn = {0898-1221}, -doi = {https://doi.org/10.1016/0898-1221(92)90124-Z}, -url = {https://www.sciencedirect.com/science/article/pii/089812219290124Z}, -author = {Hartmut Ehrig and Annegret Habel and Hans-Jörg Kreowski}, -abstract = {In the first half of this paper, we give an introductory survey on graph grammars that provide rule-based mechanisms for generating, manipulating and analyzing graphs. In the second half, two potential applications of graph-grammar concepts to semantic networks are indicated.} -} - -@book{Courcelle2009, - doi = {10.1017/cbo9780511977619}, - url = {https://doi.org/10.1017/cbo9780511977619}, - year = {2009}, - publisher = {Cambridge University Press}, - author = {Bruno Courcelle and Joost Engelfriet}, - title = {Graph Structure and Monadic Second-Order Logic} -} - -@INPROCEEDINGS{9286186, author={Elekes, Márton and Nagy, Attila and Sándor, Dávid and Antal, János Benjamin and Davis, Timothy A. and Szárnyas, Gábor}, booktitle={2020 IEEE High Performance Extreme Computing Conference (HPEC)}, title={A GraphBLAS solution to the SIGMOD 2014 Programming Contest using multi-source BFS}, year={2020}, volume={}, number={}, pages={1-7}, doi={10.1109/HPEC43674.2020.9286186}} - -@inproceedings{10.1145/3315454.3329962, -author = {Spampinato, Daniele G. and Sridhar, Upasana and Low, Tze Meng}, -title = {Linear Algebraic Depth-First Search}, -year = {2019}, -isbn = {9781450367172}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -url = {https://doi.org/10.1145/3315454.3329962}, -doi = {10.1145/3315454.3329962}, -abstract = {There is a recent push by a segment of the graph community to implement graph algorithms in the language of linear algebra. However, graph algorithms that depend on depth-first search (DFS) techniques are often highlighted as limitations of the linear algebraic approach as linear algebraic formulation of DFS algorithms are few, if any. This paper provides a linear algebraic approach for developing DFS graph algorithms and demonstrates its use for defining three classical DFS-based computations: Binary tree traversal, topological sort, and biconnected components.}, -booktitle = {Proceedings of the 6th ACM SIGPLAN International Workshop on Libraries, Languages and Compilers for Array Programming}, -pages = {93–104}, -numpages = {12}, -keywords = {post-order traversal, pre-order traversal, topological sort, biconnected components, depth-first search, adjacency matrix, graph algorithms, linear algebra, permutations}, -location = {Phoenix, AZ, USA}, -series = {ARRAY 2019} -} - -@article{GEBHARDT202241, -title = {On is an n-MCFL}, -journal = {Journal of Computer and System Sciences}, -volume = {127}, -pages = {41-52}, -year = {2022}, -issn = {0022-0000}, -doi = {https://doi.org/10.1016/j.jcss.2022.02.003}, -url = {https://www.sciencedirect.com/science/article/pii/S0022000022000174}, -author = {Kilian Gebhardt and Frédéric Meunier and Sylvain Salvati}, -keywords = {Formal Languages, Multiple Context Free Languages, Commutative Languages, Tucker Lemma, Necklace splitting theorem, Word problem in groups}, -abstract = {Commutative properties in formal languages pose problems at the frontier of computer science, computational linguistics and computational group theory. A prominent problem of this kind is the position of the language On, the language that contains the same number of letters ai and a¯i with 1⩽i⩽n, in the known classes of formal languages. It has recently been shown that On is a Multiple Context-Free Language (MCFL). However the more precise conjecture of Nederhof that On is an MCFL of dimension n was left open. We prove this conjecture using tools from algebraic topology. On our way, we prove a variant of the necklace splitting theorem.} -} - -@article{salvati:inria-00564552, - TITLE = {{MIX is a 2-MCFL and the word problem in $\mathbb{Z}^2$ is solved by a third-order collapsible pushdown automaton}}, - AUTHOR = {Salvati, Sylvain}, - URL = {https://inria.hal.science/inria-00564552}, - JOURNAL = {{Journal of Computer and System Sciences}}, - PUBLISHER = {{Elsevier}}, - VOLUME = {81}, - NUMBER = {7}, - PAGES = {1252 - 1277}, - YEAR = {2015}, - PDF = {https://inria.hal.science/inria-00564552/file/mix.pdf}, - HAL_ID = {inria-00564552}, - HAL_VERSION = {v1}, -} - -@article{10.1145/3093333.3009848, -author = {Zhang, Qirun and Su, Zhendong}, -title = {Context-Sensitive Data-Dependence Analysis via Linear Conjunctive Language Reachability}, -year = {2017}, -issue_date = {January 2017}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -volume = {52}, -number = {1}, -issn = {0362-1340}, -url = {https://doi.org/10.1145/3093333.3009848}, -doi = {10.1145/3093333.3009848}, -abstract = {Many program analysis problems can be formulated as graph reachability problems. In the literature, context-free language (CFL) reachability has been the most popular formulation and can be computed in subcubic time. The context-sensitive data-dependence analysis is a fundamental abstraction that can express a broad range of program analysis problems. It essentially describes an interleaved matched-parenthesis language reachability problem. The language is not context-free, and the problem is well-known to be undecidable. In practice, many program analyses adopt CFL-reachability to exactly model the matched parentheses for either context-sensitivity or structure-transmitted data-dependence, but not both. Thus, the CFL-reachability formulation for context-sensitive data-dependence analysis is inherently an approximation. To support more precise and scalable analyses, this paper introduces linear conjunctive language (LCL) reachability, a new, expressive class of graph reachability. LCL not only contains the interleaved matched-parenthesis language, but is also closed under all set-theoretic operations. Given a graph with n nodes and m edges, we propose an O(mn) time approximation algorithm for solving all-pairs LCL-reachability, which is asymptotically better than known CFL-reachability algorithms. Our formulation and algorithm offer a new perspective on attacking the aforementioned undecidable problem - the LCL-reachability formulation is exact, while the LCL-reachability algorithm yields a sound approximation. We have applied the LCL-reachability framework to two existing client analyses. The experimental results show that the LCL-reachability framework is both more precise and scalable than the traditional CFL-reachability framework. This paper opens up the opportunity to exploit LCL-reachability in program analysis.}, -journal = {SIGPLAN Not.}, -month = {jan}, -pages = {344–358}, -numpages = {15}, -keywords = {program analysis, Context-free language reachability, linear conjunctive grammar, trellis automata} -} - -@inproceedings{10.1145/3009837.3009848, -author = {Zhang, Qirun and Su, Zhendong}, -title = {Context-Sensitive Data-Dependence Analysis via Linear Conjunctive Language Reachability}, -year = {2017}, -isbn = {9781450346603}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -url = {https://doi.org/10.1145/3009837.3009848}, -doi = {10.1145/3009837.3009848}, -abstract = {Many program analysis problems can be formulated as graph reachability problems. In the literature, context-free language (CFL) reachability has been the most popular formulation and can be computed in subcubic time. The context-sensitive data-dependence analysis is a fundamental abstraction that can express a broad range of program analysis problems. It essentially describes an interleaved matched-parenthesis language reachability problem. The language is not context-free, and the problem is well-known to be undecidable. In practice, many program analyses adopt CFL-reachability to exactly model the matched parentheses for either context-sensitivity or structure-transmitted data-dependence, but not both. Thus, the CFL-reachability formulation for context-sensitive data-dependence analysis is inherently an approximation. To support more precise and scalable analyses, this paper introduces linear conjunctive language (LCL) reachability, a new, expressive class of graph reachability. LCL not only contains the interleaved matched-parenthesis language, but is also closed under all set-theoretic operations. Given a graph with n nodes and m edges, we propose an O(mn) time approximation algorithm for solving all-pairs LCL-reachability, which is asymptotically better than known CFL-reachability algorithms. Our formulation and algorithm offer a new perspective on attacking the aforementioned undecidable problem - the LCL-reachability formulation is exact, while the LCL-reachability algorithm yields a sound approximation. We have applied the LCL-reachability framework to two existing client analyses. The experimental results show that the LCL-reachability framework is both more precise and scalable than the traditional CFL-reachability framework. This paper opens up the opportunity to exploit LCL-reachability in program analysis.}, -booktitle = {Proceedings of the 44th ACM SIGPLAN Symposium on Principles of Programming Languages}, -pages = {344–358}, -numpages = {15}, -keywords = {program analysis, Context-free language reachability, linear conjunctive grammar, trellis automata}, -location = {Paris, France}, -series = {POPL '17} -} - -@InProceedings{10.1007/978-3-662-59620-3_5, -author="Kogkalidis, Konstantinos -and Melkonian, Orestis", -editor="Sikos, Jennifer -and Pacuit, Eric", -title="Towards a 2-Multiple Context-Free Grammar for the 3-Dimensional Dyck Language", -booktitle="At the Intersection of Language, Logic, and Information", -year="2019", -publisher="Springer Berlin Heidelberg", -address="Berlin, Heidelberg", -pages="79--92", -abstract="We discuss the open problem of parsing the Dyck language of 3 symbols, {\$}{\$}D^3{\$}{\$}, using a 2-Multiple Context-Free Grammar. We attempt to tackle this problem by implementing a number of novel meta-grammatical techniques and present the associated software packages we developed.", -isbn="978-3-662-59620-3" -} - -@inproceedings{Economopoulos2006GeneralisedLP, - title={Generalised LR parsing algorithms}, - author={Giorgios Economopoulos}, - year={2006}, - url={https://api.semanticscholar.org/CorpusID:29026667} -} - -@inproceedings{Cappers2014ExploringAV, - title={Exploring and visualizing GLL parsing}, - author={Bcm Bram Cappers}, - year={2014}, - url={https://api.semanticscholar.org/CorpusID:63190886} -} - -@inproceedings{Afroozeh2019PracticalGT, - title={Practical general top-down parsers}, - author={Ali Afroozeh and Anastasia Izmaylova}, - year={2019}, - url={https://api.semanticscholar.org/CorpusID:198351560} -} - -@article{10.1145/3571252, -author = {Koutris, Paraschos and Deep, Shaleen}, -title = {The Fine-Grained Complexity of CFL Reachability}, -year = {2023}, -issue_date = {January 2023}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -volume = {7}, -number = {POPL}, -url = {https://doi.org/10.1145/3571252}, -doi = {10.1145/3571252}, -abstract = {Many problems in static program analysis can be modeled as the context-free language (CFL) reachability problem on directed labeled graphs. The CFL reachability problem can be generally solved in time O(n3), where n is the number of vertices in the graph, with some specific cases that can be solved faster. In this work, we ask the following question: given a specific CFL, what is the exact exponent in the monomial of the running time? In other words, for which cases do we have linear, quadratic or cubic algorithms, and are there problems with intermediate runtimes? This question is inspired by recent efforts to classify classic problems in terms of their exact polynomial complexity, known as fine-grained complexity. Although recent efforts have shown some conditional lower bounds (mostly for the class of combinatorial algorithms), a general picture of the fine-grained complexity landscape for CFL reachability is missing. Our main contribution is lower bound results that pinpoint the exact running time of several classes of CFLs or specific CFLs under widely believed lower bound conjectures (e.g., Boolean Matrix Multiplication, k-Clique, APSP, 3SUM). We particularly focus on the family of Dyck-k languages (which are strings with well-matched parentheses), a fundamental class of CFL reachability problems. Remarkably, we are able to show a Ω(n2.5) lower bound for Dyck-2 reachability, which to the best of our knowledge is the first super-quadratic lower bound that applies to all algorithms, and shows that CFL reachability is strictly harder that Boolean Matrix Multiplication. We also present new lower bounds for the case of sparse input graphs where the number of edges m is the input parameter, a common setting in the database literature. For this setting, we show a cubic lower bound for Andersen’s Pointer Analysis which significantly strengthens prior known results.}, -journal = {Proc. ACM Program. Lang.}, -month = {jan}, -articleno = {59}, -numpages = {27}, -keywords = {sparse graphs, static pointer analysis, Dyck reachability, Datalog, fine-grained complexity} -} - -@misc{istomina2023finegrained, - title={Fine-grained reductions around CFL-reachability}, - author={Aleksandra Istomina and Semyon Grigorev and Ekaterina Shemetova}, - year={2023}, - eprint={2306.15967}, - archivePrefix={arXiv}, - primaryClass={cs.CC} -} - -@article{10.1145/3583660.3583664, -author = {Pavlogiannis, Andreas}, -title = {CFL/Dyck Reachability: An Algorithmic Perspective}, -year = {2023}, -issue_date = {October 2022}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -volume = {9}, -number = {4}, -url = {https://doi.org/10.1145/3583660.3583664}, -doi = {10.1145/3583660.3583664}, -abstract = {CFL/Dyck reachability is a simple graph-theoretic problem: given a CFL/Dyck language L over an alphabet Σ, a graph G = (V, E) of Σ-labeled edges, and two distinguished nodes s, t ∈ V, does there exist a path from s to t that spells out a word in L? This simple notion of language-based graph reachability serves as the algorithmic formulation of a large number of problems in diverse domains, such as graph databases and program static analysis. This paper takes an algorithmic perspective on CFL/Dyck reachability, and overviews several recent advances concerning the decidability and complexity of the problem and some its close variants, as realized in the areas of automata theory and program verification.}, -journal = {ACM SIGLOG News}, -month = {feb}, -pages = {5–25}, -numpages = {21} -} - -@inproceedings{Terekhov2021MultipleSourceCP, - title={Multiple-Source Context-Free Path Querying in Terms of Linear Algebra}, - author={Arseniy Terekhov and Vlada Pogozhelskaya and Vadim Abzalov and Timur Zinnatulin and Semyon V. Grigorev}, - booktitle={International Conference on Extending Database Technology}, - year={2021}, - url={https://api.semanticscholar.org/CorpusID:232284054} -} - -@article{10.1145/321239.321249, -author = {Brzozowski, Janusz A.}, -title = {Derivatives of Regular Expressions}, -year = {1964}, -issue_date = {Oct. 1964}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -volume = {11}, -number = {4}, -issn = {0004-5411}, -url = {https://doi.org/10.1145/321239.321249}, -doi = {10.1145/321239.321249}, -journal = {J. ACM}, -month = {oct}, -pages = {481–494}, -numpages = {14} -} - -@book{Leiss1999, - doi = {10.1007/978-1-4612-2156-2}, - url = {https://doi.org/10.1007/978-1-4612-2156-2}, - year = {1999}, - publisher = {Springer New York}, - author = {Ernst L. Leiss}, - title = {Language Equations} -} - -@article{MRYKHIN2023113829, -title = {The hardest language for grammars with context operators}, -journal = {Theoretical Computer Science}, -volume = {958}, -pages = {113829}, -year = {2023}, -issn = {0304-3975}, -doi = {https://doi.org/10.1016/j.tcs.2023.113829}, -url = {https://www.sciencedirect.com/science/article/pii/S0304397523001421}, -author = {Mikhail Mrykhin and Alexander Okhotin}, -keywords = {Formal language theory, Formal grammars, Hardest formal languages, Grammars with context operators, Inverse homomorphisms, Finite transducers}, -abstract = {In 1973, Greibach (“The hardest context-free language”, SIAM J. Comp., 1973) constructed a context-free language L0 with the property that every context-free language can be reduced to L0 by a homomorphism, thus representing it as an inverse homomorphic image h−1(L0). In this paper, a similar characterization is established for a family of grammars equipped with operators for referring to the left context of any substring, recently defined by Barash and Okhotin (“An extension of context-free grammars with one-sided context specifications”, Inform. Comput., 2014). An essential step of the argument is a new normal form for grammars with context operators, in which every nonterminal symbol defines only strings of odd length in left contexts of even length: the even-odd normal form. The characterization is completed by showing that the language family defined by grammars with context operators is closed under inverse homomorphisms; actually, it is closed under injective nondeterministic finite transductions.} -} - -@article{markov1954theory, - title={The theory of algorithms}, - author={Markov, Andrei Andreevich}, - journal={Trudy Matematicheskogo Instituta Imeni VA Steklova}, - volume={42}, - pages={3--375}, - year={1954}, - publisher={Russian Academy of Sciences, Steklov Mathematical Institute of Russian~…} -} - -@book{10.5555/578595, -author = {Harrison, M. A.}, -title = {Introduction to Formal Language Theory}, -year = {1978}, -isbn = {0201029553}, -publisher = {Addison-Wesley Longman Publishing Co., Inc.}, -address = {USA}, -edition = {1st}, -abstract = {From the Publisher:Formal language theory was fist developed in the mid 1950's in an attempt to develop theories of natural language acquisition. It was soon realized that this theory (particularly the context-free portion) was quite relevant to the artificial languages that had originated in computer science. Since those days, the theory of formal languages has been developed extensively, and has several discernible trends, which include applications to the syntactic analysis of programming languages, program schemes, models of biological systems, and relationships with natural languages.} -} - -@book{hopcroft2001introduction, - title={Introduction to automata theory, languages, and computation}, - author={Hopcroft, John E and Motwani, Rajeev and Ullman, Jeffrey D}, - journal={Acm Sigact News}, - volume={32}, - number={1}, - pages={60--65}, - year={2001}, - publisher={ACM New York, NY, USA} -} - -@article{10.1145/3591472, -author = {Jia, Xiaodong and Kumar, Ashish and Tan, Gang}, -title = {A Derivative-Based Parser Generator for Visibly Pushdown Grammars}, -year = {2023}, -issue_date = {June 2023}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -volume = {45}, -number = {2}, -issn = {0164-0925}, -url = {https://doi.org/10.1145/3591472}, -doi = {10.1145/3591472}, -abstract = {In this article, we present a derivative-based, functional recognizer and parser generator for visibly pushdown grammars. The generated parser accepts ambiguous grammars and produces a parse forest containing all valid parse trees for an input string in linear time. Each parse tree in the forest can then be extracted also in linear time. Besides the parser generator, to allow more flexible forms of the visibly pushdown grammars, we also present a translator that converts a tagged CFG to a visibly pushdown grammar in a sound way, and the parse trees of the tagged CFG are further produced by running the semantic actions embedded in the parse trees of the translated visibly pushdown grammar. The performance of the parser is compared with popular parsing tools, including ANTLR, GNU Bison, and other popular hand-crafted parsers. The correctness and the time complexity of the core parsing algorithm are formally verified in the proof assistant Coq.}, -journal = {ACM Trans. Program. Lang. Syst.}, -month = {may}, -articleno = {9}, -numpages = {68}, -keywords = {Parser generators, derivative-based parsing, formal verification} -} - -@inproceedings{10.1145/2983990.2984026, -author = {Brachth\"{a}user, Jonathan Immanuel and Rendel, Tillmann and Ostermann, Klaus}, -title = {Parsing with First-Class Derivatives}, -year = {2016}, -isbn = {9781450344449}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -url = {https://doi.org/10.1145/2983990.2984026}, -doi = {10.1145/2983990.2984026}, -abstract = {Brzozowski derivatives, well known in the context of regular expressions, have recently been rediscovered to give a simplified explanation to parsers of context-free languages. We add derivatives as a novel first-class feature to a standard parser combinator language. First-class derivatives enable an inversion of the control flow, allowing to implement modular parsers for languages that previously required separate pre-processing steps or cross-cutting modifications of the parsers. We show that our framework offers new opportunities for reuse and supports a modular definition of interesting use cases of layout-sensitive parsing.}, -booktitle = {Proceedings of the 2016 ACM SIGPLAN International Conference on Object-Oriented Programming, Systems, Languages, and Applications}, -pages = {588–606}, -numpages = {19}, -keywords = {Left Quotient, Parser Combinators, Parsing, Derivative, Modularity}, -location = {Amsterdam, Netherlands}, -series = {OOPSLA 2016} -} - -@article{10.1145/3022671.2984026, -author = {Brachth\"{a}user, Jonathan Immanuel and Rendel, Tillmann and Ostermann, Klaus}, -title = {Parsing with First-Class Derivatives}, -year = {2016}, -issue_date = {October 2016}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -volume = {51}, -number = {10}, -issn = {0362-1340}, -url = {https://doi.org/10.1145/3022671.2984026}, -doi = {10.1145/3022671.2984026}, -abstract = {Brzozowski derivatives, well known in the context of regular expressions, have recently been rediscovered to give a simplified explanation to parsers of context-free languages. We add derivatives as a novel first-class feature to a standard parser combinator language. First-class derivatives enable an inversion of the control flow, allowing to implement modular parsers for languages that previously required separate pre-processing steps or cross-cutting modifications of the parsers. We show that our framework offers new opportunities for reuse and supports a modular definition of interesting use cases of layout-sensitive parsing.}, -journal = {SIGPLAN Not.}, -month = {oct}, -pages = {588–606}, -numpages = {19}, -keywords = {Left Quotient, Parsing, Modularity, Derivative, Parser Combinators} -} - -@article{caron_champarnaud_mignot_2014, title={A general framework for the derivation of regular expressions}, volume={48}, DOI={10.1051/ita/2014010}, number={3}, journal={RAIRO - Theoretical Informatics and Applications}, publisher={EDP Sciences}, author={Caron, Pascal and Champarnaud, Jean-Marc and Mignot, Ludovic}, year={2014}, pages={281–305}} - -@article{10.1145/2034574.2034801, -author = {Might, Matthew and Darais, David and Spiewak, Daniel}, -title = {Parsing with Derivatives: A Functional Pearl}, -year = {2011}, -issue_date = {September 2011}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -volume = {46}, -number = {9}, -issn = {0362-1340}, -url = {https://doi.org/10.1145/2034574.2034801}, -doi = {10.1145/2034574.2034801}, -abstract = {We present a functional approach to parsing unrestricted context-free grammars based on Brzozowski's derivative of regular expressions. If we consider context-free grammars as recursive regular expressions, Brzozowski's equational theory extends without modification to context-free grammars (and it generalizes to parser combinators). The supporting actors in this story are three concepts familiar to functional programmers - laziness, memoization and fixed points; these allow Brzozowski's original equations to be transliterated into purely functional code in about 30 lines spread over three functions.Yet, this almost impossibly brief implementation has a drawback: its performance is sour - in both theory and practice. The culprit? Each derivative can double the size of a grammar, and with it, the cost of the next derivative.Fortunately, much of the new structure inflicted by the derivative is either dead on arrival, or it dies after the very next derivative. To eliminate it, we once again exploit laziness and memoization to transliterate an equational theory that prunes such debris into working code. Thanks to this compaction, parsing times become reasonable in practice.We equip the functional programmer with two equational theories that, when combined, make for an abbreviated understanding and implementation of a system for parsing context-free languages.}, -journal = {SIGPLAN Not.}, -month = {sep}, -pages = {189–195}, -numpages = {7}, -keywords = {derivative, context-free grammar, regular expressions, parsing, parser combinator, formal languages} -} - -@inproceedings{10.1145/2034773.2034801, -author = {Might, Matthew and Darais, David and Spiewak, Daniel}, -title = {Parsing with Derivatives: A Functional Pearl}, -year = {2011}, -isbn = {9781450308656}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -url = {https://doi.org/10.1145/2034773.2034801}, -doi = {10.1145/2034773.2034801}, -abstract = {We present a functional approach to parsing unrestricted context-free grammars based on Brzozowski's derivative of regular expressions. If we consider context-free grammars as recursive regular expressions, Brzozowski's equational theory extends without modification to context-free grammars (and it generalizes to parser combinators). The supporting actors in this story are three concepts familiar to functional programmers - laziness, memoization and fixed points; these allow Brzozowski's original equations to be transliterated into purely functional code in about 30 lines spread over three functions.Yet, this almost impossibly brief implementation has a drawback: its performance is sour - in both theory and practice. The culprit? Each derivative can double the size of a grammar, and with it, the cost of the next derivative.Fortunately, much of the new structure inflicted by the derivative is either dead on arrival, or it dies after the very next derivative. To eliminate it, we once again exploit laziness and memoization to transliterate an equational theory that prunes such debris into working code. Thanks to this compaction, parsing times become reasonable in practice.We equip the functional programmer with two equational theories that, when combined, make for an abbreviated understanding and implementation of a system for parsing context-free languages.}, -booktitle = {Proceedings of the 16th ACM SIGPLAN International Conference on Functional Programming}, -pages = {189–195}, -numpages = {7}, -keywords = {regular expressions, context-free grammar, parser combinator, formal languages, derivative, parsing}, -location = {Tokyo, Japan}, -series = {ICFP '11} -} - -@article{10.1017/S0956796808007090, -author = {Owens, Scott and Reppy, John and Turon, Aaron}, -title = {Regular-Expression Derivatives Re-Examined}, -year = {2009}, -issue_date = {March 2009}, -publisher = {Cambridge University Press}, -address = {USA}, -volume = {19}, -number = {2}, -issn = {0956-7968}, -url = {https://doi.org/10.1017/S0956796808007090}, -doi = {10.1017/S0956796808007090}, -abstract = {Regular-expression derivatives are an old, but elegant, technique for compiling regular expressions to deterministic finite-state machines. It easily supports extending the regular-expression operators with boolean operations, such as intersection and complement. Unfortunately, this technique has been lost in the sands of time and few computer scientists are aware of it. In this paper, we reexamine regular-expression derivatives and report on our experiences in the context of two different functional-language implementations. The basic implementation is simple and we show how to extend it to handle large character sets (e.g., Unicode). We also show that the derivatives approach leads to smaller state machines than the traditional algorithm given by McNaughton and Yamada.}, -journal = {J. Funct. Program.}, -month = {mar}, -pages = {173–190}, -numpages = {18} -} - -@inproceedings{10.1145/2949689.2949711, -author = {Nol\'{e}, Maurizio and Sartiani, Carlo}, -title = {Regular Path Queries on Massive Graphs}, -year = {2016}, -isbn = {9781450342155}, -publisher = {Association for Computing Machinery}, -address = {New York, NY, USA}, -url = {https://doi.org/10.1145/2949689.2949711}, -doi = {10.1145/2949689.2949711}, -abstract = {Regular Path Queries (RPQs) represent a powerful tool for querying graph databases and are of particular interest, because they form the building blocks of other query languages, and because they can be used in many theoretical or practical contexts for different purposes.In this paper we present a novel system for processing regular path queries on massive data graphs. As confirmed by an extensive experimental evaluation, our system scales linearly with the number of vertices and/or edges, and it can efficiently query graphs up to a billion vertices and 100 billion edges.}, -booktitle = {Proceedings of the 28th International Conference on Scientific and Statistical Database Management}, -articleno = {13}, -numpages = {12}, -location = {Budapest, Hungary}, -series = {SSDBM '16} -} - -@article{chomsky1958finite, - title={Finite state languages}, - author={Chomsky, Noam and Miller, George A}, - journal={Information and control}, - volume={1}, - number={2}, - pages={91--112}, - year={1958}, - publisher={Elsevier} -} \ No newline at end of file diff --git a/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex b/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex deleted file mode 100644 index b4e36b7..0000000 --- a/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex +++ /dev/null @@ -1,204 +0,0 @@ -%\documentclass[a4paper,12pt]{article} % standard LaTeX, 12 point type -\documentclass[12pt, a4paper, table]{book} - -\usepackage{algpseudocode} -\usepackage{algorithm} -\usepackage{algorithmicx} - -\usepackage{geometry} -\usepackage{amsfonts,latexsym} -\usepackage{amsthm, amsmath} -\usepackage{amssymb} -\usepackage[utf8]{inputenc} % Кодировка -\usepackage[english,russian]{babel} % Многоязычность -\usepackage{mathtools} -\usepackage{hyperref} -\usepackage[dvipsnames]{xcolor} -\usepackage{tikz} -\usepackage{dsfont} -\usepackage{multicol} -\usepackage[bb=boondox]{mathalfa} -\usepackage{subcaption} -\usepackage{fontawesome} - -\usetikzlibrary{fit,calc,automata,positioning} -\usetikzlibrary{shapes.geometric} -\usetikzlibrary{decorations.pathmorphing} - -\theoremstyle{definition} -\newtheorem{definition}{Определение}[section] -\newtheorem{example}{Пример}[section] -\newtheorem{theorem}{Теорема}[section] -\newtheorem{proposition}[theorem]{Proposition} -\newtheorem{lemma}[theorem]{Лемма} -\newtheorem{corollary}[theorem]{Corollary} -\newtheorem{conjecture}[theorem]{Conjecture} -\newtheorem{note}[theorem]{Утверждение} - - -% unnumbered environments: - -\theoremstyle{remark} -\newtheorem*{remark}{Remark} -%\newtheorem*{notation}{Notation} - -\setlength{\parskip}{5pt plus 2pt minus 1pt} -%\setlength{\parindent}{0pt} - -\tikzset{snake it/.style={decorate, decoration=snake}} -\tikzset{ - side by side/.style 2 args={ - line width=2pt, - #1, - postaction={ - clip,postaction={draw,#2} - } - } -} - -\algtext*{EndWhile}% Remove "end while" text -\algtext*{EndIf}% Remove "end if" text -\algtext*{EndFor}% Remove "end for" text -\algtext*{EndFunction}% Remove "end function" text - - -% \usepackage{color} -\usepackage{listings} -\usepackage{caption} -\usepackage{graphicx} -\usepackage{ucs} - -% \graphicspath{{pics/}} - -%\geometry{left=2cm} -%\geometry{right=1.5cm} -%\geometry{top=2cm} -%\geometry{bottom=2cm} - - - - -%\lstnewenvironment{algorithm}[1][] -%{ -% \lstset{ -% frame=tB, -% numbers=left, -% mathescape=true, -% numberstyle=\small, -% basicstyle=\small, -% inputencoding=utf8, -% extendedchars=\true, -% keywordstyle=\color{black}\bfseries, -% keywords={,function, procedure, return, datatype, function, in, if, else, for, foreach, while, denote, do, and, then, assert,} -% numbers=left, -% xleftmargin=.04\textwidth, -% #1 % this is to add specific settings to an usage of this environment (for instnce, the caption and referable label) -% } -%} -%{} - -\newcommand{\tab}[1][0.3cm]{\ensuremath{\hspace*{#1}}} - -\newcommand{\rvline}{\hspace*{-\arraycolsep}\vline\hspace*{-\arraycolsep}} - -\newcommand{\derives}[1][*]{\xRightarrow[]{#1}} -\newcommand{\first}[1][1]{\textsc{first}_{#1}} -\newcommand{\follow}[1][1]{\textsc{follow}_{#1}} - -\newcommand{\highlight}[2][yellow]{\mathchoice% - {\colorbox{#1}{$\displaystyle#2$}}% - {\colorbox{#1}{$\textstyle#2$}}% - {\colorbox{#1}{$\scriptstyle#2$}}% - {\colorbox{#1}{$\scriptscriptstyle#2$}}}% - -\setcounter{MaxMatrixCols}{20} - - -\tikzset{ -%->, % makes the edges directed -%>=stealth’, % makes the arrow heads bold -node distance=4cm, % specifies the minimum distance between two nodes. Change if necessary. -%every state/.style={thick, fill=gray!10}, % sets the properties for each ’state’ node -initial text=$ $, % sets the text that appears on the start arrow -} - -\tikzstyle{symbol_node} = [shape=rectangle, rounded corners, draw, align=center] - -\tikzstyle{r_state} = [shape=rectangle, draw, minimum size=0.2cm] - -\tikzstyle{num_state} = [draw=none, fill=none, anchor=south west, red] - -\tikzstyle{prod_node} = [shape=rectangle, draw, align=center] - -\tikzset{ - between/.style args={#1 and #2}{ - at = ($(#1)!0.5!(#2)$) - }, - >= stealth, - every state/.style={minimum size=1pt} -} - -%every node/.style = {shape=rectangle, rounded corners, -% draw, align=center, -% top color=white, bottom color=blue!20} - -\newcommand{\bfgray}[1]{\cellcolor{lightgray}\textbf{#1}} - -\newenvironment{scaledalign}[4] - { - \begingroup - #1 - \setlength\arraycolsep{#2} - \renewcommand{\arraystretch}{#3} - \begin{center} - \begin{equation} - \begin{aligned} - #4 - } - { - \end{aligned} - \end{equation} - \end{center} - \endgroup - } - -\title{О достижимости с ограничениями в терминах формальных языков} -\author{Семён Григорьев} -\date{\today} - -\begin{document} -\maketitle -\newpage -\tableofcontents -\newpage - - -\input{List_of_contributors} -\input{Introduction} -\input{LinearAlgebra} -\input{GraphTheoryIntro} -\input{FormalLanguageTheoryIntro} -\input{RegularLanguages} -\input{Context-Free_Languages} -\input{Multiple_Context-Free_Languages} -%\input{ConjunctiveAndBooleanLanguages} -\input{FLPQ} -\input{RPQ} -%\input{CFPQ} -\input{CYK_for_CFPQ} -\input{Matrix-based_CFPQ} -\input{TensorProduct} -\input{SPPF} -\input{GLL-based_CFPQ} -\input{GLR-based_CFPQ} -%\input{CombinatorsForCFPQ} -\input{Multiple_Context-Free_Language_Reachability} -%\input{DerivativesForCFPQ} -%\input{CFPQ_to_Datalog} -\input{Conclusion} - -\bibliographystyle{abbrv} -\bibliography{FormalLanguageConstrainedReachabilityLectureNotes} - - -\end{document} diff --git a/tex/FormalLanguageTheoryIntro.tex b/tex/FormalLanguageTheoryIntro.tex deleted file mode 100644 index 01fd1a9..0000000 --- a/tex/FormalLanguageTheoryIntro.tex +++ /dev/null @@ -1,297 +0,0 @@ -\chapter[Общие сведения теории формальных языков]{Общие сведения теории формальных языков\footnote{В рамках данной работы мы будем говорить о ``типичных'' языках, элементами которых являются объекты, максимально похожие на строки. При этом будет оставлен за бортом тот факт, что базовое определение позволяет нам рассматривать в качестве ``строительных элементов'' (алфавита) практически произвольные объекты, а значит, создавать весьма нетривиальные конструкции в качестве слов языка. Примерами ``нестроковых'' языков могут послужить языки деревьев~\cite{tata2007} или языки графов~\cite{EHRIG1992557, Courcelle2009}.}}\label{chpt:FormalLanguageTheoryIntro} - -В данной главе мы рассмотрим основные понятия из теории формальных языков, которые пригодятся нам в дальнейшем изложении. -Заметим, что мы рассмотрим лишь те результаты теории формальных языков,которые будут необходимы нам для дальнейшего изложения. -Для более глубокого изучения именно теории формальных языков рекомендуется обратиться к классической литературе. -Например, к работам Харрисона~\cite{10.5555/578595}, Хопкрофта~\cite{hopcroft2001introduction} или другой подобной литературе. - -\begin{definition} -\textit{Алфавит} --- это конечное множество. -Элементы этого множества будем называть \textit{символами}. -\end{definition} - -\begin{example} - Примеры алфавитов - - \begin{itemize} - \item Латинский алфавит $\Sigma = \{ a, b, c, \dots, z\}$ - \item Кириллический алфавит $\Sigma = \{ \text{а, б, в, \dots, я}\}$ - \item Алфавит натуральных чисел в шестнадцатеричной записи - $$\Sigma = \{0, 1, 2, 3, 4, 5, 6, 7 ,8,9, A, B, C, D, E, F \}$$ - \end{itemize} -\end{example} - -Традиционное обозначение для алфавита --- $\Sigma$. -Также мы будем использовать различные прописные буквы латинского алфавита. Для обозначения символов алфавита будем использовать строчные буквы латинского алфавита: $a, b, \dots, x, y, z$. - -Будем считать, что над алфавитом $\Sigma$ всегда определена операция конкатенации $(\cdot): \Sigma^* \times \Sigma^* \to \Sigma^*$. -При записи выражений символ точки (обозначение операции конкатенации) часто будем опускать: $a \cdot b = ab$. - -\begin{definition} -\textit{Слово} над алфавитом $\Sigma$ --- это конечная конкатенация символов алфавита $\Sigma$: $\omega = a_0 \cdot a_1 \cdot \ldots \cdot a_m$, где $\omega$ --- слово, а $a_i \in \Sigma$ для любого $i$. -Для обозначения пустого слова (слова, содержащего ноль символов) будем использовать специальный символ $\varepsilon, \varepsilon \notin \Sigma$. -\end{definition} - -\begin{definition} -Пусть $\omega = a_0 \cdot a_1 \cdot \ldots \cdot a_m$ --- слово над алфавитом $\Sigma$. -Будем называть $m + 1$ \textit{длиной слова} и обозначать как $|\omega|$. Длина пустого слова равна нулю. -\end{definition} - -\begin{definition} - Пусть $\omega$ --- слово над алфавитом $\Sigma$. Пусть $t \in \Sigma$ --- некоторый символ из алфавита. - Тогда будем обозначать количество вхождений символа $t$ в слове $\omega$ как $|\omega|_t$. - \end{definition} - -\begin{definition} -\textit{Язык} над алфавитом $\Sigma$ --- это множество слов над алфавитом $\Sigma$. -\end{definition} - -\begin{example} - -Примеры языков. - - \begin{itemize} - \item Язык целых чисел в двоичной записи $\{0, 1, -1, 10, 11, -10, -11, \dots\}.$ - \item Язык всех правильных скобочных последовательностей $$\{(), (()), ()(), (())(), \dots\}.$$ - \end{itemize} -\end{example} - -Любой язык над алфавитом $\Sigma$ является подмножеством универсального множества $\Sigma^*$ --- множества всех слов над алфавитом $\Sigma$. - -Заметим, что язык не обязан быть конечным множеством, в то время как алфавит в нашей области всегда конечен\footnote{Существуют ситуации, когда возникают бесконечные алфавиты.} и изучаем мы конечные слова\footnote{Существуют ситуации, когда возникают бесконечные слова. Например работы по обработке потоков.}. - -Можно выделить следующие основные \textit{способы задания языков.} -\begin{itemize} -\item Перечислить все элементы. Такой способ работает только для конечных языков. Перечислить бесконечное множество за конечное время не получится. -\item Задать генератор --- процедуру, которая возвращает очередное слово языка. -\item Задать распознаватель --- процедуру, которая по данному слову может определить, принадлежит оно заданному языку или нет. -\end{itemize} - -Стоит отметить, что существуют и другие способы задания. -Например, язык может определяться как решение некоторого \textit{языкового уравнения}~\cite{Leiss1999}. - -\section{Теоретико-множественные операции над языками} - -Так как язык --- это \textit{множество} слов, то над языками естественным образом определены теоретико-множественные операции, такие как объединение, пересечение, дополнение. -\begin{itemize} - \item $L_1 \cup L_2 = \{ \omega \mid \omega \in L_1 \text{ или } \omega \in L_2\}$ - \item $L_1 \cap L_2 = \{ \omega \mid \omega \in L_1 \text{ и } \omega \in L_2\}$ - \item $\overline{L} = \{ \omega \mid \omega \in \Sigma^* \text{ и } \omega \notin L\}$, где $L$ --- язык над алфавитом $\Sigma$ . -\end{itemize} - -Но кроме этого, нам потребуются и относительно специальные операции, определённые ниже. - -\begin{definition} -Пусть дано множество $S$ с определённой на нём операцией $\odot: S \times S \to S$, $S_1 \subseteq S$, $S_2 \subseteq S$, тогда -$$ -S_1 \odot S_2 = \{ s_1 \odot s_2 \mid s_1 \in S_1, s_2 \in S_2\} -$$ -\end{definition} - -\begin{definition} -Пусть дано множество $S$ с определённой на нём операцией $\odot: S \times S \to S$, $S_1 \subseteq S$, тогда -$$ -S_1 ^ n = \{ \underbrace{s_1 \odot s_1 \odot \ldots \odot s_1}_{\text{n раз}} \mid s_1 \in S_1\} -$$ -При этом $S_1^0 = \{\varepsilon\}$\footnote{В данном случае нулевая степень даёт единицу, как мы и привыкли.}. -\end{definition} - -\begin{definition} -Пусть дано множество $S$ с определённой на нём операцией $\odot: S \times S \to S$, $S_1 \subseteq S$, тогда -$$ -S_1 ^ * = \bigcup_{n = 0}^{\infty} S_1^n -$$ -\end{definition} - -Многие прикладные задачи, в которых возникают языки, достаточно естественным образом формулируются в теоретико-множественных терминах. -Так, задача распознавания --- это задача проверки принадлежности элемента множеству. -Далее мы рассмотрим прикладные задачи, решение которых требует, например, проверки включения одного языка в другой, или проверки непустоты пересечения двух языков. -Разрешимость таких задач, алгоритмы решения, их сложность и другие свойства, зависят от свойств языков. -Это даёт дополнительную связь теоретико-языковых конструкций с решением прикладных задач, позволяя более аккуратно рассуждать о свойствах получаемых решений. - -\section{Производные} - -Производные для языков предложил Януш Бжозовский в работе\cite{10.1145/321239.321249}. - -\begin{definition} - Производная $\partial_c L = \{ w' \mid w \in L, w = cw'\}$ -\end{definition} - -Заметим, что если для слова $w, |w|=n$ верно, что $$\varepsilon \in (\partial_{w[n-1]} \circ \ldots \circ \partial_{w[1]} \circ \partial_{w[0]}) (L)$$, то $w \in L$. -Таким образом, существует возможность использовать производные для проверки принадлежность слов заданному языку. -Данная возможность активно используется для регулярных языков~\cite{caron_champarnaud_mignot_2014}, языков, распознаваемых автоматами, управляемыми входом (Input Driven Pushdown Automata, IDPDA)~\cite{10.1145/3591472}, и контекстно-свободных языков~\cite{10.1145/2034773.2034801, 10.1145/3022671.2984026}. -Кроме этого, с помощью производных можно построить элегантный алгоритм построения конечного автомата по регулярному выражению~\cite{10.1017/S0956796808007090} и для выполнения регулярных запросов~\cite{10.1145/2949689.2949711}. - - -\section{Распознаватели} - -Распознаватель может быть сконструирован как некоторая формальная машина, которая принимает или отвергает те или иные слова, записанные на входной ленте. -Таким образом, язык задаваемый некоторым вычислителем --- это множество принимаемых им слов. -Далее становится возможно классифицировать языки по тому, какого класса распознаватель необходим и достаточен, чтобы их задать. -Например, можно выделить класс языков, задаваемых конечными автоматами. -На этом, в частности, построена \textit{иерархия Хомского}. - - - - - -\section{Генераторы} - -Один из базовых способов задать генератор языка опирается на \textit{системы переписывания строк}, из которых, в дальнейшем, можно получить так называемые \textit{порождающие грамматики}. - -\begin{definition} - \textit{Система переписывания (строк)}\footnote{Один из классически примеров систем переписывания строк --- это машины Маркова, или алгорифмы Маркова~\cite{markov1954theory}.} --- это пара $R = \langle \Sigma, P \rangle$, где $\Sigma$ --- алфавит, $P= \{p \mid p = w' \to w'', w' \in \Sigma^+, w'' \in \Sigma^*\}$ --- набор правил переписывания. -\end{definition} - -Один шаг работы системы состоит из замены любого вхождения любой из левых частей правил на соответствующую правую часть правила. -Иными словами, пусть есть слово $w = w_0w_1w_2$ и имеется правило $w_1 \to w_3 \in P$. -Тогда после переписывания по этому правилу будет получено слово $w' = w_0w_3w_2$. -Заметим, что выбор заменяемого вхождения, как и выбор применяемого правила недетерминирован: может быть выбрано любое из вхождений и применено любое из доступных правил. -В качестве критерия остановки выберем невозможность применить ни одно из доступных правил. -Получившееся при этом слово будем считать результатом работы машины. -Зафиксировав стартовую строку и набор правил, можно достаточно естественным образом получить язык, как множество всех слов, являющихся результатом работы машины. - -Представленная система является, скорее, неформальной базой для создания более содержательных систем. -Далее, накладывая дополнительные ограничения на правила машины и алгоритм её работы, мы будем получать некоторые содержательные классы языков. - -Отметим, что подход к определению языков через системы переписывания не всегда удобен. Например, не получается с их использованием естественным образом определить булевы языки. - - -\section{Классы языков} - -Иерархия языков, предложенная Ноамом Хомским (Noam Chomsky), является на текущий момент классической и представлена на рисунке~\ref{fig:Chomsky}. -Она основана на сопоставлении языкам тех или иных формальных вычислителей, способных их распознать. -Например, для распознавания любого регулярного языка достаточно конечного автомата. Для контекстно-свободного --- магазинного автомата. И так далее. - - -\begin{figure} - \begin{center} - \includegraphics[width=0.9\textwidth]{figures/Chomsky.pdf} - \end{center} - \caption{Иерархия языков по Хомскому} - \label{fig:Chomsky} -\end{figure} - -Однако, данная иерархия постепенно теряет свою актуальность, так как появляются новые классы языков, свойства которых уже не удаётся адекватным образом отобразить, используя её. - -Один из вариантов иерархии языков, более полно отображающий современное состояние дел, предложен Александром Охотиным\footnote{Иерархия и некоторые отражаемые ей свойства подробно обсуждаются в презентации Александра Охотина ``Underlying principles -and recurring ideas of formal grammars'' (\url{https://users.math-cs.spbu.ru/~okhotin/talks/grammars_lata_talk.pdf}). -Также, с данной презентацией рекомендуется ознакомиться чтобы представить себе состояние области в целом.}. -Вариация предложенной Александром Охотиным иерархии представлена на изображении~\ref{fig:hierarchyOkhotin}~\footnote{Данная вариация скомпонована из версии, представленной в презентации ``Underlying principles -and recurring ideas of formal grammars'' и версии, взятой из работы~\cite{MRYKHIN2023113829}.}. -Приведённая диаграмма содержит регулярные и контекстно-свободные. -Так и подклассы, лежащие между ними. -Вместе с этим, классы, лежащие выше контекстно-свободных: многокомпонентные контекстно-свободные, булевы, конъюнктивные, их подклассы. - -\begin{figure} - \begin{center} - \begin{tikzpicture}[node distance=1.0cm,bend angle=45,auto] - \tikzstyle{lang}=[circle,thick,draw=blue!75,fill=blue!75,minimum size=1mm] - \node [lang] (reg) [label=below:\textit{Reg}] {}; - \node [right of = reg] (reg_dummy) {}; - \node [lang] (lllin) [right of=reg_dummy, label=below:\textit{LLLin}] {}; - \node [right of = lllin] (lllin_dummy) {}; - \node [lang] (lrlin) [right of=lllin_dummy, label=below:\textit{LRLin}] {}; - \node [right of = lrlin] (lrlin_dummy) {}; - \node [lang] (unamblin) [right of=lrlin_dummy, label=below:\textit{UnambLin}] {}; - \node [right of = unamblin] (unamblin_dummy) {}; - \node [lang] (lin) [right of=unamblin_dummy, label=below:\textit{Lin}] {}; - \node [right of = lin] (lin_dummy) {}; - \node [right of = lin_dummy] (lin_dummy_2) {}; - \node [right of = lin_dummy_2] (lin_dummy_3) {}; - \node [lang] (conj) [right of=lin_dummy_3, label=below:\textit{Conj}] {}; - \node [right of = conj] (conj_dummy) {}; - \node [lang] (bool) [right of=conj_dummy, label=right:\textit{Bool}] {}; - - \node [above of = lrlin] (lrlin_up_dummy) {}; - \node [lang] (ll) [above of=lrlin_up_dummy, label=above:\textit{LL}] {}; - \node [right of = ll] (ll_dummy) {}; - \node [lang] (lr) [right of=ll_dummy, label=above:\textit{LR}] {}; - \node [right of = lr] (lr_dummy) {}; - \node [lang] (unamb) [right of=lr_dummy, label=above:\textit{Unamb}] {}; - \node [right of = unamb] (unamb_dummy) {}; - \node [lang] (ordinary) [right of=unamb_dummy, label=right:\textit{Ordinary}] {}; - - \node [lang] (conjleftcontext) [above of=conj_dummy, label=right:\textit{Conj$+\lhd$}] {}; - - \node [below of = lrlin] (lrlin_down_dummy) {}; - \node [lang] (vpda) [below of=lrlin_down_dummy, label=below:\textit{VPDA}] {}; - \node [below of = lin] (lin_down_dummy_1) {}; - \node [below of = lin_down_dummy_1] (lin_down_dummy_2) {}; - \node [right of = lin_down_dummy_2] (lin_right_dummy_1) {}; - \node [lang] (linconj) [right of=lin_right_dummy_1, label=below:\textit{LinConj}] {}; - - \node [lang] (unambtag) [above of=unamb_dummy, label=above:\textit{UnambTAG}] {}; - \node [right of = unambtag] (unambtag_dummy) {}; - \node [lang] (tag) [right of=unambtag_dummy, label=above:\textit{TAG}] {}; - \node [right of = tag] (tag_dummy) {}; - \node [lang] (mcfl) [right of=tag_dummy, label=above:\textit{MCFL}] {}; - - \node [above of = linconj] (linconj_above_dummy) {}; - \node [lang] (unambconj) [right of=linconj_above_dummy, label=below:\textit{UnambConj}] {}; - \node [right of = unambconj] (unambconj_dummy) {}; - \node [lang] (unambbool) [right of=unambconj_dummy, label=right:\textit{UnambBool}] {}; - - \node [below of = linconj] (linconj_below_dummy) {}; - \node [lang] (rtca) [right of=linconj_below_dummy, label=below:\textit{RT-CA}] {}; - \node [right of = rtca] (rtca_dummy) {}; - \node [lang] (ltca) [right of=rtca_dummy, label=right:\textit{LT-CA}] {}; - - \path[->] - (reg) edge node {} (lllin) - (lllin) edge node {} (lrlin) - (lrlin) edge node {} (unamblin) - (unamblin) edge node {} (lin) - - (lllin) edge node {} (ll) - (ll) edge node {} (lr) - (ll) edge node {} (lr) - (lr) edge node {} (unamb) - (unamb) edge node {} (ordinary) - - (lrlin) edge node {} (lr) - (unamblin) edge node {} (unamb) - (lin) edge node {} (ordinary) - - (reg) edge node {} (vpda) - (vpda) edge node {} (lr) - (vpda) edge node {} (linconj) - - (ordinary) edge node {} (conj) - (conj) edge node {} (bool) - (conj) edge node {} (conjleftcontext) - - (unamb) edge node {} (unambtag) - (ordinary) edge node {} (tag) - (unambtag) edge node {} (tag) - (tag) edge node {} (mcfl) - - (lin) edge node {} (linconj) - (linconj) edge node {} (unambconj) - (unambconj) edge node {} (unambbool) - (unambconj) edge node {} (conj) - (unambbool) edge node {} (bool) - (unamb) edge node {} (unambconj) - - (linconj) edge node {} (rtca) - (rtca) edge node {} (ltca) - ; - \end{tikzpicture} -\end{center} -\caption{Иерархия. \textit{Reg} --- регулярные, \textit{LLLin}, \textit{LRLin}, \textit{UnambLin}, \textit{Lin}, \textit{LL}, \textit{LR}, \textit{Unamb} --- однозначные, \textit{Ordinary} --- обыкновенные (контекстно-свободные) -\textit{Conj} --- конъюнктивные, \textit{Boolean} --- булевы, \textit{UnamnbBool}, \textit{UnambConj}, \textit{VPDA}, \textit{LinConj}, \textit{UnambTAG}, \textit{TAG}, \textit{MCFL},} -\label{fig:hierarchyOkhotin} -\end{figure} - -Для того, чтобы содержательно рассуждать про различные классы языков, необходимо иметь механизм, позволяющий чётко отделить один класс от другого. -\textit{Лемма о накачке} для соответствующего класса --- один из классических таких механизмов. -Однако, не для всех классов языков соответствующие результаты получены. -Так, например, формулировка леммы о накачки для многокомпонентных контекстно-свободных языков в общем виде всё ещё не найдена, хотя существуют формулировки для отдельных подклассов. -Аналогично, для булевых и конъюнктивных языков всё ещё не предложены аналоги лемм о накачке. - - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item !!! -% \item !!! -%\end{enumerate} diff --git a/tex/GLL-based_CFPQ.tex b/tex/GLL-based_CFPQ.tex deleted file mode 100644 index 2f5f7dd..0000000 --- a/tex/GLL-based_CFPQ.tex +++ /dev/null @@ -1,647 +0,0 @@ -\chapter{Алгоритм на основе нисходящего анализа} - -В данном разделе мы рассмотрим семейство алгоритмов нисходящего синтаксического (рекурсивный спуск, LL, GLL~\cite{Scott:2010:GP:1860132.1860320,10.1007/978-3-662-46663-6_5}) и их обобщение для задачи поиска путей с контекстно-свободными ограничениями. - -% и GLL~\cite{Grigorev:2017:CPQ:3166094.3166104} Другие реализации~\cite{MEDEIROS201975} - -\section{Рекурсивный спуск} - -Идея рекурсивного спуска основана на использовании программного стека вызовов в качестве стека магазинного автомата. Достигается это следующим образом. -\begin{itemize} - \item Для каждого нетерминала создаётся функция, принимающая ещё не обработанный остаток строки и возвращающая пару: результат вывода префикса данной строки из соответствующего нетерминала и не обработанный остаток строки. В случае распознавателя результат вывода --- логическое значение (выводится/не выводится). - \item Каждая такая функция реализовывает обработку цепочки согласно правым частям правил для соответствующих нетерминалов: считывание символа входа при обработке терминального символа, вызов соответствующей функции при обработке нетерминального. -\end{itemize} - -У такого подхода есть два ограничения: -\begin{enumerate} - \item Не работает с леворекурсивными грамматиками, то есть грамматиками, вывод в которых может принимать следующий вид: - $$ - S \to \cdots \to \underline{N_i} \alpha \to \cdots \underline{N_i} \beta \to \cdots \omega - $$ - \item Шаги должны быть однозначными. -\end{enumerate} - -\begin{example} - -Построим функцию рекурсивного спуска для продукции $S \rightarrow aSbS \mid \varepsilon$. - -\begin{algorithm} - \floatname{algorithm}{Listing} -\begin{algorithmic}[1] -\caption{Функция рекурсивного спуска} -\Function{S}{$\omega$} - \If {(len$(\omega)=0$)} - \Comment{{\footnotesize Пустая цепочка выводима из $S$}} - \State{\Return \textit{(true, $\omega$)}} - \EndIf - - \If{$(\omega = a :: tl)$} - \Comment{{\footnotesize Выводимая из $S$ подстрока должна начинаться с $a$}} - \State{$res,tl' = $ S($tl$)} - \Comment{{\footnotesize Затем должна идти подстрока, выводимая из $S$}} - \If{res \&\& $tl' = b :: tl''$} - \Comment{{\footnotesize Если вызов закончился успешно, то надо проверить, что следующий символ --- это $b$}} - \State{\Return $S(tl'')$} - \Comment{{\footnotesize И снова попробовать вывести перфикс из $S$}} - \Else - \State{\Return \textit{(false, $tl'$)}} - \EndIf - \Else - \State{\Return \textit{(false, $\omega$)}} - \EndIf -\EndFunction - -\end{algorithmic} -\end{algorithm} -\end{example} - -Если возвращаеммое значение этой функции --- пара вида \textit{(true, [])}, то разбор завершился успехом. - -Данный подход применяется как для ручного написания синтаксических нализаторов, так и при генерации анализаторов по грамматике. - -\section{LL(k)-алгоритм синтаксического анализа} - -LL(k) --- алгоритм синтаксического анализа --- нисходящий анализ без отката, но с предпросмотром. -Решение о том, какую продукцию применять, принимается на основании k следующих за текущим символом. -Временная сложность алгоритма $O(n)$, где $n$~--- длина слова. - -Алгоритм использует входной буфер, стек для хранения промежуточных данных и таблицу анализатора, которая управляет процессом разбора. -В ячейке таблицы указано правило, которое нужно применять, если рассматривается нетерминал $A$, а следующие $m$ символов строки~--- $t_{1} \dots t_{m}$, где $m \leq k$. -Также в таблице выделена отдельная колонка для $\$$~--- маркера конца строки. - -\begin{center} - \begin{tabular}{ c || c | c | c | c } - & $\dots$ & $t_{1} \dots t_{m}$ & $\dots$ & $\$$ \\ \hline - $\dots$ & $\dots$ & $\dots$ & $\dots$ & $\dots$ \\ \hline - $A$ & $\dots$ & $A \to \alpha$ & $\dots$ & $\dots$ \\ \hline - $\dots$ & $\dots$ & $\dots$ & $\dots$ & $\dots$ - \end{tabular} -\end{center} - -Для построения таблицы вычисляются множества $\first[k]$ и $\follow[k]$. Идейно их можно понимать, как первые или, соответственно, последующие $k$ символов в результирующем выводе, при использовании нетерминала $A$. Данную мысль хорошо иллюстрирует рисунок: - -\begin{center} - \begin{tikzpicture} - \draw[black, thick] (0,0) -- (2,4); - \draw[black, thick] (2,4) -- (4,0); - \draw[black, thick] (1,0) -- (2,2); - \draw[black, thick] (2,2) -- (3,0); - \draw[black, thick] (2,2) -- (3,0); - \draw[black, thick] (0,0) -- (1,0); - \draw[red, ultra thick] (1,0) -- (1.75,0); - \draw[black, thick] (1.75,0) -- (3,0); - \draw[red, ultra thick] (3,0) -- (3.75,0); - \draw[black, thick] (3.75,0) -- (4,0); - \filldraw[black] (2,4) circle (1pt) node[anchor=west] {S}; - \filldraw[black] (2,2) circle (1pt) node[anchor=west] {A}; - \filldraw[black] (0,0) circle (0pt) - node[anchor=east] {\textbf{$\omega$}}; - \filldraw[red] (1.5,0) circle (0pt) - node[anchor=north] {\footnotesize $\first[k](A)$}; - \filldraw[red] (3.75,0) circle (0pt) - node[anchor=north] {\footnotesize $\follow[k](A)$}; - \end{tikzpicture} -\end{center} - -Определим их формально: - -\begin{definition} - Пусть $G = \langle N, \Sigma, P, S \rangle$~--- КС-грамматика. Множество $\first[k]$ определено для сентенциальной формы $\alpha$ следующим образом: - \[ \first[k](\alpha) = \{ \omega \in \Sigma^* \mid \alpha \derives{} \omega \text{ и } |\omega| < k \text{ либо } \exists \beta: \alpha \derives{} \omega \beta \text{ и } |\omega| = k \} - \] - , где $\alpha, \beta \in (N \cup \Sigma)^*.$ -\end{definition} - -\begin{definition} - Пусть $G = \langle N, \Sigma, P, S \rangle$~--- КС-грамматика. Множество $\follow[k]$ определено для сентенциальной формы $\beta$ следующим образом: - \[\follow[k](\beta) = \{ \omega \in \Sigma^* \mid \exists \gamma, \alpha: S \derives{} \gamma \beta \alpha \text{ и } \omega \in \first[k](\alpha) \} \] -\end{definition} - -В частном случае для $k = 1$: - -\[ \first(\alpha) = \{ a \in \Sigma \mid \exists \gamma \in (N \cup \Sigma)^*: \alpha \derives{} a \gamma \} \text{, где } \alpha \in (N \cup \Sigma)^* \} \] - -\[ \follow(\beta) = \{ a \in \Sigma \mid \exists \gamma, \alpha \in (N \cup \Sigma)^* : S \derives{} \gamma \beta a \alpha \} \text{, где } \beta \in (N \cup \Sigma)^* \} \] - -Множество $\first$ можно вычислить, пользуясь следующими соотношениями: - -\begin{itemize} - \item $\first(a \alpha) = \{a\}, a \in \Sigma, \alpha \in (N \cup \Sigma)^* $ - \item $\first(\varepsilon) = \{\varepsilon\}$ - \item $\first(\alpha \beta) = \first(\alpha) \cup (\first(\beta) \text{, если } \varepsilon \in \first(\alpha))$ - \item $\first(A) = \first(\alpha) \cup \first(\beta) \text{, если в грамматике есть правила } A \to \alpha \mid\beta$ -\end{itemize} - -Алгоритм для вычисления множества $\follow$: - -\begin{itemize} - \item Положим $\follow(X) = \varnothing, \forall X \in N$ - \item $\follow(S) = \follow(S) \cup \{\$\} \text{, где } S \text{--- стартовый нетерминал}$ - \item Для всех правил вида $A \to \alpha X \beta: \follow(X) = \follow(X) \cup (\first(\beta) \setminus \{\varepsilon\} )$ - \item Для всех правил вида $A \to \alpha X \text{ и } A \to \alpha X \beta \text{, где } \varepsilon \in \first(\beta): \follow(X) = \follow(X) \cup \follow(A)$ - \item Последние два пункта применяются, пока есть что добавлять в строящиеся множества. -\end{itemize} - - -\begin{example} - -Рассмотрим грамматику $G$ со следующими продукциями: -\begin{align*} - S &\to a S' & A' \to b \mid a \\ - S' &\to A b B S' \mid \varepsilon & B \to c \mid \varepsilon\\ - A &\to a A' \mid \varepsilon -\end{align*} - - -Пример множеств $\first$ для нетерминалов грамматики $G$: - -\begin{multicols}{2} - -\columnbreak - -\begin{align*} - \first(S) &= \{ a \} & \first(B) &= \{ c, \varepsilon \} \\ - \first(A) &= \{ a, \varepsilon \} & \first(S') &= \{ a, b, \varepsilon \}\\ - \first(A') &= \{ a, b \} -\end{align*} -\end{multicols} - -Пример множеств $\follow$ для нетерминалов грамматики $G$: - -\begin{align*} - \follow(S) &= \{ \$ \} & \\ - \follow(S') &= \{ \$ \} &(S \to a S')\\ - \follow(A) &= \{ b \} &(S' \to A b B S') \\ - \follow(A') &= \{ b \} &(A \to a A')\\ - \follow(B) &= \{ a, b, \$ \} &(S' \to A b B S', \varepsilon \in \first(S')) -\end{align*} - -\end{example} - -Управляющая таблица LL(k) анализатора заполняется следующим образом: продукции $A \to \alpha, \alpha \neq \varepsilon$ помещаются в ячейки $(A, a)$, где $a \in \first(\alpha)$, продукции $A \to \alpha$~--- в ячейки $(A, a)$, где $a \in \follow(A)$, если $\varepsilon \in \first(\alpha)$ - -\begin{example} - -Пример таблицы для грамматики $S \to aSbS \mid \varepsilon$ - -\begin{center} -\begin{tabular}{ r || c | c || c | c | c } -N & $\first$ & $\follow$ & a & b & $\$ $ \\ \hline -$S$ & $\{ a, \varepsilon \}$ & $\{ b, \$ \}$ & $S \rightarrow aSbS$ & $S \rightarrow \varepsilon$ & $S \rightarrow \varepsilon$ -\end{tabular} -\end{center} - -\end{example} - -Однако, не для всех грамматик по множествам $\first[k]$ и $\follow[k]$ возможно выбрать применяемую продукцию, а значит, нельзя однозначно построить таблицу, необходимую для работы алгоритма, поэтому данный алгоритм применим только для грамматик особого класса --- LL(k). - -\begin{definition} - LL(k) грамматика --- грамматика, для которой на основании множеств $\first[k]$ и $\follow[k]$ можно однозначно определить, какую продукцию применять. -\end{definition} - -Важно заметить, что при больших $k$ управляющая таблица сильно разрастается, поэтому на практике данный алгоритм применим для небольших значений $k$. - -Интерпретатор автомата принимает входную строку и построенную управляющую таблицу и работает следующим образом. -В каждый момент времени конфигурация автомата это позиция во входной строке и стек. -В начальный момент времени стек пуст, а позиция во входной строке соответствует её началу. -На первом шаге в стек добавляются последовательно сперва символ конца строки, затем стартовый нетерминал. -На каждом шаге анализируется существующая конфигурация и совершается одно из действий. -\begin{itemize} -\item Если текущая позиция --- конец строки и вершина стека --- символ конца строки, то успешно завершаем разбор. -\item Если текущая вершина стека --- терминал, то проверяем, что позиция в строке соответствует этому терминалу. Если да, то снимаем элемент со стека, сдвигаем позицию на единицу и продолжаем разбор. Иначе завершаем разбор с ошибкой. -\item Если текущая вершина стека --- нетерминал $N_i$ и текущий входной символ $t_j$, то ищем в управляющей таблице ячейку с координатами $(N_i, t_j)$ и записываем на стек содержимое этой ячейки. -\end{itemize} - -\begin{example}Пример работы LL анализатора. -Рассмотрим грамматику $S \to aSbS \mid \varepsilon$ и выводимое слово $\omega = abab$. - -Расмотрим пошагово работу алгоритма, будем использовать таблицу, построенную в предыдущем примере: - -\begin{enumerate} - \item Начало работы. - - Стек: \, - \begin{tabular}[c]{ |c| } - \\ \hline - \$ \\ \hline - \end{tabular} - \qquad \qquad \qquad \qquad входное слово: \, - \begin{tabular}[c]{ |c|c|c|c|c| } - \hline - \textcolor{red}{a} & b & a & b & \$ \\ \hline - \end{tabular} - -Финальный символ лежит на стеке, а указатель указывает на первый символ слова. - - \item кладем стартовый символ на стек - - Стек: \, - \begin{tabular}[c]{ |c| } - \\ \hline - $S$ \\ \hline - \$ \\ \hline - \end{tabular} - \qquad \qquad \qquad \qquad входное слово: \, - \begin{tabular}[c]{ |c|c|c|c|c| } - \hline - \textcolor{red}{a} & b & a & b & \$ \\ \hline - \end{tabular} - - \item Ищем ячейку с координатами (S, a), применяем продукцию из ячейки. - - Стек: \, - \begin{tabular}[c]{ |c| } - \\ \hline - $a$ \\ \hline - $S$ \\ \hline - $b$ \\ \hline - $S$ \\ \hline - \$ \\ \hline - \end{tabular} - \qquad \qquad \qquad \qquad входное слово: \, - \begin{tabular}[c]{ |c|c|c|c|c| } - \hline - \textcolor{red}{a} & b & a & b & \$ \\ \hline - \end{tabular} - -\item Снимаем терминал $a$ со стека и двигаем указатель. - - Стек: \, - \begin{tabular}[c]{ |c| } - \\ \hline - $S$ \\ \hline - $b$ \\ \hline - $S$ \\ \hline - \$ \\ \hline - \end{tabular} - \qquad \qquad \qquad \qquad входное слово: \, - \begin{tabular}[c]{ |c|c|c|c|c| } - \hline - a & \textcolor{red}{b} & a & b & \$ \\ \hline - \end{tabular} - -\item Ищем ячейку с координатами (S, b), применяем продукцию из ячейки. - - Стек: \, - \begin{tabular}[c]{ |c| } - \\ \hline - $b$ \\ \hline - $S$ \\ \hline - \$ \\ \hline - \end{tabular} - \qquad \qquad \qquad \qquad входное слово: \, - \begin{tabular}[c]{ |c|c|c|c|c| } - \hline - a & \textcolor{red}{b} & a & b & \$ \\ \hline - \end{tabular} - -\item Снимаем терминал $b$ со стека и двигаем указатель. - - Стек: \, - \begin{tabular}[c]{ |c| } - \\ \hline - $S$ \\ \hline - \$ \\ \hline - \end{tabular} - \qquad \qquad \qquad \qquad входное слово: \, - \begin{tabular}[c]{ |c|c|c|c|c| } - \hline - a & b & \textcolor{red}{a} & b & \$ \\ \hline - \end{tabular} - - \item Ищем ячейку с координатами (S, a), применяем продукцию из ячейки. - - Стек: \, - \begin{tabular}[c]{ |c| } - \\ \hline - $a$ \\ \hline - $S$ \\ \hline - $b$ \\ \hline - $S$ \\ \hline - \$ \\ \hline - \end{tabular} - \qquad \qquad \qquad \qquad входное слово: \, - \begin{tabular}[c]{ |c|c|c|c|c| } - \hline - a & b & \textcolor{red}{a} & b & \$ \\ \hline - \end{tabular} - -\item Снимаем терминал $a$ со стека и двигаем указатель. - - Стек: \, - \begin{tabular}[c]{ |c| } - \\ \hline - $S$ \\ \hline - $b$ \\ \hline - $S$ \\ \hline - \$ \\ \hline - \end{tabular} - \qquad \qquad \qquad \qquad входное слово: \, - \begin{tabular}[c]{ |c|c|c|c|c| } - \hline - a & b & a & \textcolor{red}{b} & \$ \\ \hline - \end{tabular} - -\item Ищем ячейку с координатами (S, b), применяем продукцию из ячейки. - - Стек: \, - \begin{tabular}[c]{ |c| } - \\ \hline - $b$ \\ \hline - $S$ \\ \hline - \$ \\ \hline - \end{tabular} - \qquad \qquad \qquad \qquad входное слово: \, - \begin{tabular}[c]{ |c|c|c|c|c| } - \hline - a & b & a & \textcolor{red}{b} & \$ \\ \hline - \end{tabular} - -\item Снимаем терминал $b$ со стека и двигаем указатель. - - Стек: \, - \begin{tabular}[c]{ |c| } - \\ \hline - $S$ \\ \hline - \$ \\ \hline - \end{tabular} - \qquad \qquad \qquad \qquad входное слово: \, - \begin{tabular}[c]{ |c|c|c|c|c| } - \hline - a & b & a & b & \textcolor{red}{\$} \\ \hline - \end{tabular} - -\item Ищем ячейку с координатами (S, \$), применяем продукцию из ячейки. - - Стек: \, - \begin{tabular}[c]{ |c| } - \\ \hline - \$ \\ \hline - \end{tabular} - \qquad \qquad \qquad \qquad входное слово: \, - \begin{tabular}[c]{ |c|c|c|c|c| } - \hline - a & b & a & b & \textcolor{red}{\$} \\ \hline - \end{tabular} - -\item Оказались в конце строки и на вершине стека символ конца --- завершаем разбор. - -\end{enumerate} - -\end{example} - -Можно расширить данный алгоритм так, чтобы он строил дерево вывода. Дерево будет строиться сверху вниз, от корня к листьям. Для этого необходимо расширить шаги алгоритма. -\begin{itemize} - \item В ситуации, когда мы читаем очередной терминал (на вершине стека и во входе одинаковые терминалы), мы создаём лист с соответствующим терминалом. - \item В ситуации, когда мы заменяем нетерминал на стеке на правую часть продукции в соответствии с управляющей таблицей, мы создаём нетерминальный узел соответствующий применяемой продукции. -\end{itemize} - -Данное семейство алгоритмов всё так же не работает с леворекурсивными грамматиками и с неоднозначными грамматиками. - -Таким образом, по некоторым грамматикам можно построить LL(k) анализатор (назовём их LL(k) грамматиками), но не по всем. -С левой рекурсией, конечно, можно бороться, так как существуют алгоритмы устранения левой и скрытой левой рекурсии, а вот с неоднозначностями ничего не поделаешь. - - - -\section{Алгоритм Generalized LL} - -Можно построить анализатор, работающий с произвольными КС-грамматиками. -Generalized LL (GLL)~\cite{Scott:2010:GP:1860132.1860320,10.1007/978-3-662-46663-6_5} - -Обзор:~\cite{Cappers2014ExploringAV}, история и т.д.~\cite{Afroozeh2019PracticalGT} - -Принцип работы остается абсолютно таким же, как для табличного LL: -\begin{itemize} - \item Сначала по грамматике строится \textit{управляющая} таблица - \item Затем построенная таблица команд и непосредственно анализируемое слово поступают на вход абстрактному интерпретатору. - \item Для своей работы интерпретатор поддерживает некоторую вспомогательную структуру данных (стек для LL). - \item Один шаг разбора состоит в том, чтобы рассмотреть текущую позицию в слове, применить все соответствующие ей правила из таблицы и при возможности сдвинуть позицию разбора вправо. -\end{itemize} - -Где в этой схеме возникают ограничения на вид обрабатываемой грамматики для алгоритма LL? На самом первом шаге --- при построении таблицы может возникнуть ситуация, когда одному нетерминалу $N_j$ и последовательности $first_k(N_j)$ соответствует несколько продукций грамматики. В этом случае грамматика признавалась не соответствующей классу LL(k) и отвергалась анализатором. - -Теперь же мы разрешим такую ситуацию и в этом случае в ячейку таблицы будем записывать все продукции грамматики, соответствующие этой ячейке. Однако сразу же возникает вопрос --- а что делать интерпретатору, когда при разборе ему необходимо применить правило, состоящее из нескольких продукций? Общий ответ такой --- необходим некоторый вид недетерминизма, при котором интерпретатор мог бы ``параллельно'' обрабатывать несколько возможных вариантов синтаксического разбора. - -Эти два свойства (модифицированная управляющая таблица и недетерминизм) суть главные принципиальные отличия GLL(k) от LL(k). Далее мы перейдем к рассмотрению непосредственно технической реализации описанного алгоритма. - -Нам необходимо научиться задавать различные ветви (пути) синтаксического разбора и переключаться между ними. Заметим, что состояние любой ветви в любой момент времени суть следующее: необходимо распознать символ $N_j \in N \cup \Sigma$ из продукции $X$, начиная с элемента слова под индексом $i$. Т.е. имеем позицию в слове и позицию символа в продукции. Последнее принято называть \textit{слотом грамматики}. - -\begin{definition} - Пусть $G = \langle N, \Sigma, P, S \rangle$~--- КС-грамматика. \textit{Слотом грамматики} $G$ (позицией грамматики $G$) назовем пару из продукции $X \in P$ и позиции $0 \leq q \leq length(body(X))$ тела продукции $X$. При этом введем следующее обозначение $X ::= \alpha \cdot \beta, \quad \alpha,\beta \in (N \cup \Sigma)^*$, где $ \cdot $ указывает на позицию в продукции. -\end{definition} - -Описанная пара позиций уже однозначно задает состояние синтаксического разбора. Имеем множество состояний и переходов между ними --- возникает естественное желание воспользоваться терминами графов для представления этой структуры. Такую конструкцию называют \textit{граф-структурированный стек} или \textit{GSS} (Graph Structured Stack), который впервые был предложен Масару Томитой ~\cite{tomita1988graph} в контексте восходящего анализа. GSS будет являться рабочей структурой нашего нового интерпретатора вместо стека для LL. Состояние разбора вместе с узлом GSS мы будет называть \textit{дескриптором}. - -\begin{definition} - Пусть $G = \langle N, \Sigma, P, S \rangle$~--- КС-грамматика, $X$~--- слот грамматики $G$, $i$~--- позиция в слове $ w $ над алфавитом $\Sigma$, а $ u $~--- узел GSS. \textit{Дескриптором} назовём тройку $ (X, u, i) $. -\end{definition} - -Есть несколько способов задания GSS для алгоритма GLL. Вариант, предложенный самими авторами алгоритма, оперирует непосредственно парами из позиции слова и слота грамматики в качестве состояний (и узлов графа). Такой метод является довольно простым и наглядным, но, как описано в работе \cite{10.1007/978-3-662-46663-6_5}, не самым эффективным. Предложим сразу чуть более оптимальное представление: заметим, что шаги разбора, соответствующие одному и тому же нетерминалу и позиции слова, должны выдавать один и тот же результат независимо от конкретной продукции грамматики, в которой стоит этот нетерминал. Поэтому заводить по узлу на каждый слот грамматики довольно избыточно --- вместо этого в качестве состояния будем использовать пары из нетерминала и позиции слова, а позиции грамматики будем записывать на рёбрах. - -Итак, мы научились задавать состояния с помощью дескрипторов, а также определились со вспомогательной структурой GSS. Теперь можно перейти к рассмотрению непосредственно самого алгоритма, суть которого довольно проста и напоминает BFS по неявному графу. - -Дескриптор задает состояние, которое необходимо обработать. При этом мы без какой-либо дополнительной информации можем продолжить анализ входа из состояния, задаваемого этим дескриптором. В процессе обработки мы можем получить несколько новых состояний. Поэтому будем поддерживать множество $ R $ дескрипторов на обработку --- на каждом шаге извлекаем один из множества, проводим анализ и добавляем во множество новые полученные. - -При каких условиях этот процесс будет конечен? Ну, например, если мы каждое состояние будем обрабатывать не более одного раза. И действительно, поскольку наш интерпретатор является ``чистым'' в том смысле, что для одного и того же состояния каждый раз будут получены одинаковые результаты, проводить анализ дважды не имеет смысла. Поэтому будем также поддерживать множество $ U $ всех полученных в ходе разбора дескрипторов, и добавлять в $ R $ только те, которых еще нет в $ U $. - -И наконец, заключительная и самая главная часть --- как происходит обработка дескриптора? -Пусть дескриптор имеет вид $ (X, u, i) $, а входное слово обозначим $ W $. Есть три возможных варианта, в зависимости от вида позиции грамматики $ X $ --- разберем каждый из них по отдельности; - -\begin{itemize} - \item $ X ::= \alpha \cdot t \beta $, т.е. указатель смотрит на терминал --- в этом случае новых дескрипторов добавлено не будет. Если $ W[i] = t $, то мы сдвигаем указатель слота, переходя к рассмотрению $ X ::= \alpha t \cdot \beta $, и инкрементируем позицию $ i $ в слове. В противном же случае сразу переходим к следующему дескриптору, таким образом терминируя текущую ветвь разбора. - - \item $ X ::= \alpha \cdot A \beta $, т.е. указатель смотрит на нетерминал. Нам нужен GSS узел $ v $ вида $ (A, i) $ и ребро $ (u, X ::= \alpha A \cdot \beta, v) $ (ребро из $ u $ в $ v $ с пометкой $ X ::= \alpha A \cdot \beta $). Если такой узел и ребро уже существуют в нашем GSS, берем их, иначе --- создаём. Далее в $ R $ добавляем по дескриптору для узла $ v $ и каждого правила грамматики из ячейки управляющей таблицы для нетерминала $ A $ (конечно, если их еще не было в $ U $). На этом обработка текущего дескриптора завершается. - - \item $ X ::= \alpha \cdot $, т.е. указатель находится в конце продукции. Продукция разобрана, а значит, интерпретатору необходимо вернуться из разбора $ X $ к вызывающему правилу и продолжить разбор там (это, в некотором смысле, соответствует возврату из функции разбора нетерминала в методе рекурсивного спуска). По каждому исходящему ребру $ (u, Y, v) $ добавляем (если уже не существует) дескриптор $(Y, v, i)$. -\end{itemize} - -Результатом синтаксического разбора является успех тогда и только тогда, когда был достигнут дескриптор вида $ (S ::= \alpha \cdot, s, n) $, где слот грамматики представляет собой любое правило для аксиомы $ S $, узел GSS $ s $ состоит из аксиомы $ S $ и 0, а позиция входного слова равна его длине $ n $. Если же после разбора всех полученных дескрипторов указанный найден не был, результатом будет являться провал. - -Давайте посмотрим, как такой алгоритм справится с неоднозачной грамматикой с леворекурсивным правилом. - -\begin{example} - \label{gll:example1} - Пусть грамматика $ G $ имеет вид $ S \to SSS \mid SS \mid a $, а разбираемое слово $ w = aaa $. Тогда GSS, соответствующий разбору $S \Rightarrow SSS \Rightarrow aSS \Rightarrow aaS \Rightarrow aaa$, будет выглядеть следующим образом (для удобства каждое ребро дополнительно пронумеровано): - - \begin{center} - \input{figures/gll/complete.tex} - \end{center} - - Далее мы пошагово рассмотрим процесс его построения, а пока отметим несколько особенностей: - - \begin{itemize} - \item Это \textit{неполный} GSS. Для задачи синтаксического анализа такого достаточно, поскольку если в какой-то момент был достигнут финальный дескриптор, то обрабатывать все последующие уже не нужно. Однако, для задачи построения SPPF, как мы отметим далее, это уже не так, поскольку она требует агрегирования всех возможных путей разбора. - - \item Обратите особое внимание на наличие петель. Они как раз-таки и обеспечивают эффективную работу с леворекурсивными правилами, поскольку переиспользуются уже существующие узлы. При этом кратных петель, понятно, не создается, т.к. мы запоминаем все достигнутые дескрипторы в множестве $ U $ и дублирующих дескрипторов в рабочее множество $ R $ не добавляем. - - \item В GSS не создаются узлы, соответствующие разбору терминалов (например, $a, 0$). В действительности так можно было бы сделать. Но тогда при обработке слота, указывающего на терминал, сначала бы создался узел GSS, затем интерпретатор сверил бы терминал и символ в слове, после чего, если они совпали, произошел бы возврат из узла, а если нет, узел был бы отброшен и интерпретатор перешел бы к другому дескриптору. Таким образом, при любом случае сначала создается узел, затем выполняется проверка, после чего узел сразу отбрасывается. Для того, чтобы не создавать такие ``одноразовые'' узлы, проверка терминалов выполняется in-place. - \end{itemize} - - Пронумеруем продукции и выпишем управляющую таблицу: - - \begin{table}[!htb] - \begin{minipage}{.5\linewidth} - \centering - \begin{tabular}{lc} - $S \to S S S$ & (0) \\ - $S \to S S$ & (1) \\ - $S \to a$ & (2) - \end{tabular} - \end{minipage}% - \begin{minipage}{.5\linewidth} - \centering - \begin{tabular}{ r || c || c | c} - N & $\first$ & a & $\$ $ \\ \hline - $S$ & $\{ a \}$ & 0,1,2 & - \end{tabular} - \end{minipage} - \end{table} - - Разумеется, что конкретный порядок исполнения алгоритма будет зависеть, например, от используемой в качестве рабочего множества $ R $ структуры данных и от порядка обработки правил из ячейки управляющей таблицы. Рассмотрим лишь один из возможных вариантов: - - \begin{enumerate} - \item Для начала мы создаем узел GSS $ s_0 = (S, 0) $ и дескрипторы для правил из ячейки таблицы $ S, a $: $ (S \to \cdot SSS, s_0, 0), (S \to \cdot SS, s_0, 0), (S \to \cdot a, s_0, 0) $. - - \begin{center} - \input{figures/gll/state0.tex} - \end{center} - - \item При обработке $ (S \to \cdot S S S, s_0, 0) $ образовываются петля 1 и дескрипторы \linebreak $ (S \to \cdot SSS, s_0, 0), (S \to \cdot SS, s_0, 0), (S \to \cdot a, s_0, 0) $, которые уже содержатся в множестве $ U $ после шага 1 и поэтому не добавляются повторно. - - \begin{center} - \input{figures/gll/state1.tex} - \end{center} - - \item При обработке $ (S \to \cdot S S, s_0, 0) $ образовывается петля 2, а в остальном аналогично \mbox{шагу 2.} - - \begin{center} - \input{figures/gll/state2.tex} - \end{center} - - \item При обработке $ (S \to \cdot a, s_0, 0) $ мы распознаем терминал $a$ на позиции 0 и, возвращаясь по петлям 1 и 2, добавляем дескрипторы $ (S \to S \cdot S S, s_0, 1), (S \to S \cdot S, s_0, 1) $. - - \item При обработке $ (S \to S \cdot S S, s_0, 1) $ образовываем узел $s_1 = (S, 1)$ с исходящим ребром 3 и добавляем дескрипторы $ (S \to \cdot SSS, s_1, 1), (S \to \cdot SS, s_1, 1), (S \to \cdot a, s_1, 1) $. - - \begin{center} - \input{figures/gll/state3.tex} - \end{center} - - \item При обработке $ (S \to S \cdot S, s_0, 1) $ образовываем ребро 4, новых дескрипторов не добавляется. - - \begin{center} - \input{figures/gll/state4.tex} - \end{center} - - \item Обработка дескриптора $ (S \to \cdot S S S, s_1, 1) $ аналогична шагу 2 с добавлением петли 5. - - \begin{center} - \input{figures/gll/state5.tex} - \end{center} - - \item Обработка дескриптора $ (S \to \cdot S S, s_1, 1) $ аналогична шагу 3 с добавлением петли 6. - - \begin{center} - \input{figures/gll/state6.tex} - \end{center} - - \item При обработке $ (S \to \cdot a, s_1, 1) $ мы распознаем терминал $a$ на позиции 1 и, возвращаясь по ребрам 3 и 4, добавляем дескрипторы $ (S \to S S \cdot S, s_0, 2), (S \to S S \cdot, s_0, 2) $, а также, возвращаясь по петлям 5 и 6, добавляем дескрипторы $ (S \to S \cdot S S, s_1, 2), (S \to S \cdot S, s_1, 2) $. - - \item При обработке $ (S \to S S \cdot S, s_0, 2) $ образовываем узел $s_2 = (S, 2)$ с исходящим ребром 7 и добавляем дескрипторы $ (S \to \cdot SSS, s_2, 2), (S \to \cdot SS, s_2, 2), (S \to \cdot a, s_2, 2) $. - - \begin{center} - \input{figures/gll/state7.tex} - \end{center} - - \item Обработка дескриптора $ (S \to \cdot S S S, s_2, 2) $ аналогична шагу 2 с добавлением петли 8. - - \begin{center} - \input{figures/gll/state8.tex} - \end{center} - - \item Обработка дескриптора $ (S \to \cdot S S, s_2, 2) $ аналогична шагу 3 с добавлением петли 9. - - \begin{center} - \input{figures/gll/complete.tex} - \end{center} - - \item При обработке $ (S \to \cdot a, s_2, 2) $ мы распознаем терминал $a$ на позиции 2 и, возвращаясь по ребру 7, добавляем дескриптор $ (S \to S S S \cdot, s_0, 3) $, а также, возвращаясь по петлям 8 и 9, добавляем дескрипторы $ (S \to S \cdot S S, s_2, 3), (S \to S \cdot S, s_2, 3) $. - - \item Мы достигли финального дескриптора $ (S \to S S S \cdot, s_0, 3) $, синтаксический разбор успешен. - \end{enumerate} - -\end{example} - -Внимательный читатель мог заметить, что если бы в этом примере шаг 4 был выполнен перед шагом 2, разбор довольно быстро бы завершился неудачей. Отсюда вытекает следующее наблюдение: если в какой-то момент из существующего узла появилось новое ребро, необходимо пересчитать все входящие в него пути. - -Для построения SPPF требуется внести лишь несколько небольших добавлений: - -\begin{enumerate} - \item В дескриптор необходимо добавить узел SPPF $ w $, который будет представлять уже разобранный префикс. - \item Необходимо поддерживать множество $ P $ из элементов вида $ (u, z) $, где $ u $ это узел GSS, а $ z $ соответствующий ему узел SPPF, для того, чтобы переиспользовать результаты разбора, ассоциированные с узлами GSS. - \item При обработке терминала $ t $ на позиции $ i $ ищется узел вида $ (t, i, i + 1) $, либо создается, если такого еще нет. - \item При обработке нетерминала с помощью $ P $ ищется или при необходимости создается промежуточный узел вида $ (X, l, r) $, где $ X $ соответствующий слот грамматики, а $ l $ и $ r $ узлы SPPF, отвечающие за разбор левой и правой частей слота соответственно. -\end{enumerate} - -Конкретные шаги построения SPPF будут зависеть от выбранного для него формата. Описание эффективного бинаризованного SPPF и детали его построения при выполнении GLL представлены в работе~\cite{10.1007/978-3-662-46663-6_5}. - - \section{Алгоритм вычисления КС запросов на основе GLL} - -GLL довольно естественно обобщается на граф~\cite{Grigorev:2017:CPQ:3166094.3166104}: позициями входа теперь будем считать не индексы линейного слова, а вершины графа. В самом же алгоритме требуется внести лишь два небольших дополнения: - -\begin{enumerate} - \item Теперь при обработке терминала ``следующих'' символов может быть несколько --- рассматриваем каждый из них отдельно, сдвигаясь по соответствующему ребру. В результате, при одном чтении можем получить несколько новых дескрипторов, но они независимы, потому просто ставим их в рабочее множество $ R $. - \item При обработке нетерминала, аналогично, правила управляющей таблицы применяются для каждого из ``следующих'' символов в графе. Соответственно новых дескрипторов будет сгенерировано больше, но все они по-прежнему независимы и просто добавляются в рабочее множество $ R $. -\end{enumerate} - -Подробное описание алгоритма и псевдокод представлены в работе~\cite{Grigorev:2017:CPQ:3166094.3166104}. Существует ещё одно обобщение нисходящего синтаксического анализа для решения задачи КС достижимости~\cite{MEDEIROS201975}, которое предполагает непосредственное обобщение LL(k) алгоритма, что приводит к аналогичному результату, однако теряется связь с некоторыми построениями. - -Основанный на нисходящем анализе алгоритма поиска путей с контекстно-свободными ограничениями имеет следующие особенности. -\begin{enumerate} - \item Необходимо явно задавать начальную вершину, поэтому хорошо подходит для задач поиска путей с одним источником (single-source) или с небольшим количеством источников. Для поиска путей между всеми парами вершин необходимо явным образом все указать стартовыми. - \item Является направленным сверху вниз --- обходит граф последовательно начиная с указанной стартовой вершины и строит вывод, начиная со стартового нетерминала. Как следствие, в отличие от алгоритмов на основе линейной алгебры и Хеллингса, обойдёт только подграф, необходимый для построения ответа. В среднем это меньше, чем весь граф, который обрабатывается другими алгоритмами. - \item Естественным образом строит множество путей в виде сжатого леса разбора. - \item Использует существенно более тяжеловесные стуктуры данных и плохо распараллеливается (на практике). Как следствие, при решении задачи достижимости для всех пар путей проигрывает алгоритмам на основе линейной алгебры. -\end{enumerate} - -Частным случаем применения задачи КС достижимости является синтаксический анализ с неоднозначной токенизацией, то есть ситуацией, когда несколько пересекающихся подстрок во входной строке символов могут задавать разные лексические единицы и не возможно сделать однозначный выбор на этапе лексического анализа. -Например, для строки \verb|x = a---b| возможны несколько вариантов токенизации. -\begin{enumerate} - \item \verb|ID(x) OP_EQ ID(a) OP_MINUS OP_DECRIMENT ID(b)| - %\item \verb|ID(x) OP_EQ ID(A) OP_MINUS OP_UN_MINUS ID(b)| - \item \verb|ID(x) OP_EQ ID(a) OP_DECRIMENT OP_MINUS ID(b)| -\end{enumerate} - -В таком случае на вход синтаксическому анализатору можно подать DAG, содержащий все возможные варианты токенизации. Для нашего примера он может выглядеть следующим образом: - -\begin{center} - \begin{tikzpicture}[node distance=4cm,shorten >=1pt,on grid,auto] - \node[state] (q_0) at (0,0) {$0$}; - \node[state] (q_1) at (2.5,0) {$1$}; - \node[state] (q_2) at (5.5,0) {$2$}; - \node[state] (q_3) at (8,0) {$3$}; - \node[state] (q_4) at (10,-2) {$4$}; - \node[state] (q_5) at (11.5,0) {$6$}; - \node[state] (q_6) at (10,2) {$5$}; - \node[state] (q_7) at (14,0) {$7$}; - \path[->] - (q_0) edge node {ID(x)} (q_1) - (q_1) edge node {OP\_EQ} (q_2) - (q_2) edge node {ID(a)} (q_3) - (q_3) edge[left] node {OP\_MINUS} (q_4) - (q_4) edge[right] node {OP\_DECRIMENT} (q_5) - (q_3) edge node {OP\_DECRIMENT} (q_6) - (q_6) edge node {OP\_MINUS} (q_5) - (q_5) edge node {ID(b)} (q_7); - \end{tikzpicture} -\end{center} - -Далее будем проверять наличие пути из старовой (нулевой) вершины в конечную (соответствующую концу строки). Если таких путей оказалось несколько, то нужны дополнительные средства для выбора нужного дерева разбора. Данная идея рассматривается в работе~\cite{10.1145/3357766.3359532}. - -Напоследок сделаем небольшое замечание об эффективной реализации: в качестве рабочего множества $ R $ можно использовать несколько различных структур данных и, как правило, выбирают очередь. Однако иногда (в особенности для графов) лучше использовать стек дескрипторов, так как в этом случае выше локальность данных --- мы кладём пачку дескрипторов, соответствующих исходящим рёбрам. И если граф представлен списком смежности, то исходящие будут храниться рядом и их лучше обработать сразу. - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item Проведите алгоритм GLL для грамматики $ S \to a S b S \mid \varepsilon$. Правда ли, что эта грамматика принадлежит классу $ LL(1) $? Пронаблюдайте, как использование GSS вырождается в работу с обычным стеком. -% \item Доразберите все не рассмотренные в примере \ref{gll:example1} дескрипторы, постройте полный GSS. -%\end{enumerate} - diff --git a/tex/GLR-based_CFPQ.tex b/tex/GLR-based_CFPQ.tex deleted file mode 100644 index 6d67bf8..0000000 --- a/tex/GLR-based_CFPQ.tex +++ /dev/null @@ -1,1159 +0,0 @@ -\chapter{Алгоритм на основе восходящего анализа}\label{chpt:GLR} - -В данном разделе будут рассмотрены алгоритмы восходящего синтаксического анализа LR-семейства, в том числе Generalized LR (GLR). Также будет рассмотрено обобщение алгоритма GLR для решения задачи поиска путей с контекстно-свободными ограничениями в графах. - -\section{Восходящий синтаксический анализ} - -Существует большое семейство LR(k) алгоритмов --- алгоритм восходящего синтаксического анализа. -Основная идея, лежащая в основе семейства, заключается в следующем: входная последовательность символов считывается слева направо с попутным добавлением в стек и выполнением сворачивания на стеке --- замены последовательности терминалов и нетерминалов, лежащих наверху стека, на нетерминал, если существует соответствующее правило в исходной грамматике. - -Как и в случае с LL, используется магазинный автомат, управляемый таблицами, построенными по грамматике. -При этом, у LR анализатора есть два типа команд: -\begin{enumerate} - \item shift --- прочитать следующий символ входной последовательности, положив его в стек, и перейти в следующее состояние; - \item reduce(k) --- применить k-ое правило грамматики, правая часть которого уже лежит на стеке: снимаем со стека правую часть продукции и кладём левую часть. -\end{enumerate} - -А управляющая таблица выглядит следующим образом. - -\begin{center} - \begin{tabular}{c||c|c|c|c|c||c|c|c|c} - States & $t_0$ &$\dots$ & $t_a$ & $\dots$ & \$ & $N_0$ &$\dots$ & $N_b$ & $\dots$ \\ \hline \hline - $\dots$ & $\dots$ &$\dots$ & $\dots$ & $\dots$ & $\dots$ & $\dots$ &$\dots$ & $\dots$ & $\dots$ \\ \hline - $10$ & $\dots$ &$\dots$ & $s_i$ & $\dots$ & $r_k$ & $\dots$ &$\dots$ & $j$ & $\dots$ \\ \hline - $\dots$ & $\dots$ &$\dots$ & $\dots$ & $\dots$ & $acc$ & $\dots$ &$\dots$ & $\dots$ & $\dots$ - \end{tabular} -\end{center} - -Здесь -\begin{itemize} - \item $s_i$~--- shift: перенести соответствующи символ в стек и перейти в состояние $i$. - \item $r_k$~--- reduce(k): в стеке накопилась правая часть продукции $k$, пора производить свёртку. - \item $j$~--- goto: выполняется после reduce. Сама по себе команда reduce не переводит автомат в новое состояние. Команда goto переведёт автомат в состояние $j$. - \item $acc$~--- accept: разбор завершился успешно. -\end{itemize} - -Если ячейка пустая и в процессе работы мы пропали в неё --- значит произошла ошибка. Для детерминированной работы анализатора требуется, чтобы в каждой ячейке было не более одной команды. Есди это не так, то говорят о возникновении конфликтов. - -\begin{itemize} -\item shift-reduce --- ситуация, когда не понятно, читать ли следующий символ или выполнить свёртку. Например, если правая часть одного из правил является префиксом правой части другого правила: $N \rightarrow w, M \rightarrow ww'$. -\item reduce-reduce --- ситуация, когда не понятно, к какому правилу нужно применить свёртку. -Например, если есть два правила с одинаковыми правыми частями: $N \rightarrow w, M \rightarrow w$. -\end{itemize} - -Принцип работы LR анализаторов следующий. Пусть у нас есть входная строка, LR-автомат со стеком и управляющая таблица. -В начальный момент на стеке лежит стартовое состояние LR-автомата, позиция во входной строке соответствует её началу. -На каждом шаге анализируется текущий символ входа и текущее состояние, в котором находится автомат, и совершается одно из действий: -\begin{itemize} -\item Если в управляющей таблице нет инструкции для текущего состояния автомата и текущего символа на входе, то завершаем разбор с ошибкой. -\item Иначе выполняем одну из инструкций: -\begin{itemize} -\item в случае acc --- успешно завершаем разбор. -\item в случае shift --- кладем на стек текущий символ входа, сдвигая при этом текущую позицию, и номер нового состояния. Переходим в новое состояние. -\item в случае reduce(k) --- снимаем со стека 2l элементов: l состояний и l терминалов/нетерминалов (где l --- длина правой части k-ого правила), кладём на стек нетерминал левой части правила. Тперь на вершине стека у нас нетерминал $N_a$, а следующий элемент --- состяние $i$. Если в ячейке $(i,N_a)$ управляющей таблицы лежит состояние $j$, то кладём его на вершину стека. Иначе завершаемся с ошибкой. -\end{itemize} -\end{itemize} - - -Разные алгоритмы из LR-семейства строят таблицы разными способами и, соответственно, могут избегать тех или иных конфликтов. Рассмотрим некоторых представителей. - -\subsection{LR(0) алгоритм} - -Данный алгоритм самый ``слабый'' из семейства: разбирает наименьший класс языков. -Для построения используются LR(0) пункты. - -\begin{definition} -LR(0) пункт (LR(0) item) --- правило грамматики, в правой части которого имеется точка, отделяющая уже разобранную часть правила (слева от точки) от того, что еще предстоит распознать (справа от точки): $A \to \alpha \cdot \beta$, где $A \to \alpha \beta$~--- правило грамматики. -\qed -\end{definition} - -Состояние LR(0) автомата --- множество LR(0) пунктов. Для их построения используется операция \textit{closure} или \textit{замыкание}. - -\begin{definition} -$closure(X) = closure(X \cup \{M \rightarrow \cdot \gamma \mid N_i \rightarrow \alpha\cdot M\beta \in X \})$ -\qed -\end{definition} - -\begin{definition} -Ядро --- исходное множество пунктов, до применения к нему замыкания. -\qed -\end{definition} - -Для перемещения точки в пункте используется функция \textit{goto}. - -\begin{definition} -$goto(X,p) = \{N_j \rightarrow \alpha p \cdot \beta \mid N_j \rightarrow \alpha\cdot p\beta \in X \}$ -\qed -\end{definition} - -Теперь мы можем построить LR(0) автомат. -Первым шагом необходимо расширить грамматику: добавить к исходной грамматике правило вида $S' \to S \$$, где $S$ --- стартовый нетерминал исходной грамматики, $S'$ --- новый стартовый нетерминал (не использовался ранее в грамматике), $\$$ --- маркер конца строки (не входил в терминальный алфавит исходной грамматики). - -Далее строим автомат по следующим принципам. - -\begin{itemize} - \item Состояния~--- множества пунктов. - \item Переходы между состяниями осуществляются по символам грамматики. - \item Начальное состояние~--- $closure(\{S'\to - \cdot S \$\})$. - \item Следующее состояние по текущему состоянию $X$ и смволу $p$ вычисляются как $closure(goto(X, p))$ - \end{itemize} - -Управляющая таблица по автомату строится следующим образом. - -\begin{itemize} - \item $acc$ в ячейку, соответствующую финальному состоянию и \$ - \item $s_i$ в ячейку $(j,t)$, если в автомате есть переход из состояния $j$ по терминалу $t$ в состояние $i$ - \item $i$ в ячейку $(j, N)$, если в автомате есть переход из состояния $j$ по нетерминалу $N$ в состояние $i$ - \item $r_k$ в ячейку $(j,t)$, если в состоянии $j$ есть пункт $A \to \alpha \cdot$, где $A \to \alpha$~--- $k$-ое правило грамматики, $t$~--- терминал грамматики - \end{itemize} - -\subsection{SLR(1) алгоритм} - -SLR(1) анализатор отличается от LR(0) анализатора построением таблицы по автомату (автомат в точности, как у LR(0). -А именно, $r_k$ добавляется в ячейку $(j,t)$, если в состоянии $j$ есть пункт $A \to \alpha \cdot$, где $A \to \alpha$~--- $k$-ое правило грамматики, $t \in FOLLOW(A)$ - -\subsection{CLR(1) алгоритм} - -Canonical LR(1), он же LR(1). -Данный алгоритм является дальнейшим расширением SLR(1): к пунктам добавляются множества предпросмотра (lookahead). - -\begin{definition} -Множество предпросмотра для правила $P$ --- терминалы, которые должны встретиться в выведенной строке сразу после строки, выводимой из данного правила. -\qed -\end{definition} - -\begin{definition} -CLR пункт: $ [A \to \alpha \cdot \beta, \{ t_0, \dots, t_n\}] $, -где $t_0, \dots, t_n$ --- множество предпросмотра для правила $A \to \alpha \beta$. -\qed -\end{definition} - - -\begin{definition} -Пусть дана грамматика $G = \langle \Sigma, N, R, S\rangle$. -\begin{align*} - closure(X) = closure(X \cup \{&[B \to \cdot \delta, \{FIRST(\beta t_0), \dots, FIRST(\beta t_n)\}] \\ - &\mid B \to \beta \in R, [A \to \alpha \cdot B \beta, \{t_0, \dots, t_n\}] \in closure(X)\}) -\end{align*} -\qed -\end{definition} - -Функция \textit{goto} определяется аналогично LR(0), автомат строится по тем же принципам. - -При построении управляющей таблицы усиливается правило добавлеия команды \textit{redice}. -А именно, добавляем $r_k$ в ячейку $(j,t_i)$, если в состоянии $j$ есть пункт $[A \to \alpha \cdot, \{t_0, \dots, t_n\}]$, где $A \to \alpha$~--- $k$-ое правило грамматики. - -\subsection{Примеры} - -Рассмотрим построение автоматов и таблиц для различных модификаций LR алгоритма. - -Возьмем следующую грамматику: -\begin{align*} -0) S & \rightarrow a S b S \\ -1) S & \rightarrow \varepsilon -\end{align*} - -Расширим вышеупомянутую грамматику, добавив новый стартовый нетерминал S', и далее будем работать с этой расширенной грамматикой: -\begin{align*} -0)& S \rightarrow a S b S \\ -1)& S \rightarrow \varepsilon \\ -2)& S' \rightarrow S \$ -\end{align*} - - -\begin{example} -Пример ядра и замыкания. - -Возьмем правило 2 нашей грамматики, предположим, что мы только начинаем разбирать данное правило. - -Ядром в таком случае является item исходного правила: $S' \rightarrow \cdot S \$$ - -При замыкании добавятся ещё два item'a с правилами по выводу нетерминала `$S$', поэтому получаем три item'a: $S' \rightarrow \cdot S\$$, $S \rightarrow \cdot aSbS$ и $S \rightarrow \cdot \varepsilon$ -\end{example} - -\begin{example} -Пример построения LR(0)-автомата для нашей грамматики с применением замыкания. -\begin{enumerate} -\item Добавляем стартовое состояние: item правила 0 и его замыкание (вместо item'a $S \rightarrow .\varepsilon$ будем писать $S \rightarrow .$). - -\input{figures/GLR/LR0/state0.tex} - -\item По `$S$' добавляем переход из стартового состояния в новое состояние 1. - -\input{figures/GLR/LR0/state1.tex} - -\item По '$\$$' добавляем переход из состояния 1 в новое состояние 2. - -\input{figures/GLR/LR0/state2.tex} - -\item По `$a$' добавляем переход из стартового состояния в новое состояние 3 и делаем его замыкание. Также добавляем переход по `$a$' из этого состояния в себя же. - -\input{figures/GLR/LR0/state3.tex} - -\item По `$S$' добавляем переход из состояния 3 в новое состояние 4. - -\input{figures/GLR/LR0/state4.tex} - -\item По `$b$' добавляем переход из состояния 4 в новое состояние 5 и делаем его замыкание. Также добавляем переход по `$a$' из этого состояния в состояние 3. - -\input{figures/GLR/LR0/state5.tex} - - -\item По `$S$' добавляем переход из состояния 5 в новое состояние 6. Завершаем построение LR-автомата. - -\input{figures/GLR/LR0/complete.tex} - -\end{enumerate} -\end{example} - -Далее будем использовать этот автомат для построения управляющей таблицы. - -\begin{example} -Пример управляющей LR(0) таблицы. - -\begin{tabular}{c||c|c|c||c} - & a & b & \$ & S \\ \hline - \hline 0 & $s_3$, $r_1$ & $r_1$ & $r_1$ & 1 \\ - \hline 1 & & & acc & \\ - \hline 2 & $r_2$ & $r_2$ & $r_2$ & \\ - \hline 3 & $s_3$, $r_1$ & $r_1$ & $r_1$ & 4 \\ - \hline 4 & & $s_5$ & & \\ - \hline 5 & $s_3, r_1$ & $r_1$ & $r_1$ & 6 \\ - \hline 6 & $r_0$ & $r_0$ & $r_0$ & - -\end{tabular} - -Как видим, в данном случае в таблице присутствуют shift-reduce конфликты. В случае, когда не удаётся построить таблицу без конфликтов, говорят, что грамматика не LR(0). - -\qed -\end{example} - - -\begin{example} -Пример управляющей LR(1) таблицы. Автомат тот же, однако команды \textit{reduce} расставляются с использованием FOLLOW. - -$$ -\textit{FOLLOW}_1(S) = \{b, \$\} -$$ - -\begin{tabular}{c||c|c|c||c} - & a & b & \$ & S \\ \hline - \hline 0 & $s_3$ & $r_1$ & $r_1$ & 1 \\ - \hline 1 & & & acc & \\ - \hline 2 & & & & \\ - \hline 3 & $s_3$ & $r_1$ & $r_1$ & 4 \\ - \hline 4 & & $s_5$ & & \\ - \hline 5 & $s_3$ & $r_1$ & $r_1$ & 6 \\ - \hline 6 & & $r_0$ & $r_0$ & \\ [1ex] -\end{tabular} - -В данном случае в таблице отсутствуют shift-reduce конфликты. То есть наша грамматика SLR(1), но не LR(0). - -\qed -\end{example} - -\begin{example} -Пример LR-разбора входного слова abab\$ из языка нашей грамматики с использованием построенных ранее LR-автомата и управляющей таблицы. -\begin{enumerate} -\item Начало разбора. На стеке --- стартовое состояние 0. \\ \\ -Вход: \, -\begin{tabular}[c]{ |c|c|c|c|c| } - \hline \textcolor{red}{a} & b & a & b & \$ \\ \hline -\end{tabular} \\ -Стек: \, -\begin{tabular}[c]{ |c|c } - \hline 0 & \\ \hline -\end{tabular} -\\ -\item Выполняем shift 3: сдвигаем указатель на входе, кладем на стек `$a$', новое состояние 3 и переходим в него. \\ \\ -Вход: \, -\begin{tabular}[c]{ |c|c|c|c|c| } - \hline a & \textcolor{red}{b} & a & b & \$ \\ \hline -\end{tabular} \\ -Стек: \, -\begin{tabular}[c]{ |c|c|c|c } - \hline 0 & a & 3 & \\ \hline -\end{tabular} -\\ -\item Выполняем reduce 1 (кладем на стек `$S$'), кладем новое состояние 4 и переходим в него. \\ \\ -Вход: \, -\begin{tabular}[c]{ |c|c|c|c|c| } - \hline a & \textcolor{red}{b} & a & b & \$ \\ \hline -\end{tabular} \\ -Стек: \, -\begin{tabular}[c]{ |c|c|c|c|c|c } - \hline 0 & a & 3 & S & 4 & \\ \hline -\end{tabular} -\\ -\item Выполняем shift 5: сдвигаем указатель на входе, кладем на стек `$b$', новое состояние 5 и переходим в него. \\ \\ -Вход: \, -\begin{tabular}[c]{ |c|c|c|c|c| } - \hline a & b & \textcolor{red}{a} & b & \$ \\ \hline -\end{tabular}\\ -Стек: \, -\begin{tabular}[c]{ |c|c|c|c|c|c|c|c } - \hline 0 & a & 3 & S & 4 & b & 5 & \\ \hline -\end{tabular} -\\ -\item Выполняем shift 3. \\ \\ -Вход: \, -\begin{tabular}[c]{ |c|c|c|c|c| } - \hline a & b & a & \textcolor{red}{b} & \$ \\ \hline -\end{tabular} \\ -Стек: \, -\begin{tabular}[c]{ |c|c|c|c|c|c|c|c|c|c } - \hline 0 & a & 3 & S & 4 & b & 5 & a & 3 & \\ \hline -\end{tabular} -\\ -\item Выполняем reduce 1, кладем новое состояние 4 и переходим в него. \\ \\ -Вход: \, -\begin{tabular}[c]{ |c|c|c|c|c| } - \hline a & b & a & \textcolor{red}{b} & \$ \\ \hline -\end{tabular}\\ -Стек: \, -\begin{tabular}[c]{ |c|c|c|c|c|c|c|c|c|c|c|c } - \hline 0 & a & 3 & S & 4 & b & 5 & a & 3 & S & 4 & \\ \hline -\end{tabular} -\\ -\item Выполняем shift 5. \\ \\ -Вход: \, -\begin{tabular}[c]{ |c|c|c|c|c| } - \hline a & b & a & b & \textcolor{red}{\$} \\ \hline -\end{tabular} \\ -Стек: \, -\begin{tabular}[c]{ |c|c|c|c|c|c|c|c|c|c|c|c|c|c } - \hline 0 & a & 3 & S & 4 & b & 5 & a & 3 & S & 4 & b & 5 & \\ \hline -\end{tabular} -\\ -\item Выполняем reduce 1, кладем новое состояние 6 и переходим в него. \\ \\ -Вход: \, -\begin{tabular}[c]{ |c|c|c|c|c| } - \hline a & b & a & b & \textcolor{red}{\$} \\ \hline -\end{tabular} \\ -Стек: \, -\begin{tabular}[c]{ |c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c } - \hline 0 & a & 3 & S & 4 & b & 5 & a & 3 & S & 4 & b & 5 & S & 6 & \\ \hline -\end{tabular} -\\ -\item Выполняем reduce 0 (снимаем со стека 8 элементов и кладем `$S$'), оказываемся в состоянии 5 и делаем переход в новое состояние 6 с добавлением его на стек. \\ \\ -Вход: \, -\begin{tabular}[c]{ |c|c|c|c|c| } - \hline a & b & a & b & \textcolor{red}{\$} \\ \hline -\end{tabular}\\ -Стек: \, -\begin{tabular}[c]{ |c|c|c|c|c|c|c|c|c|c } - \hline 0 & a & 3 & S & 4 & b & 5 & S & 6 & \\ \hline -\end{tabular} -\\ -\item Снова выполняем reduce 0, оказываемся в состоянии 0 и делаем переход в новое состояние 1 с добавлением его на стек. Заканчиваем разбор. \\ \\ -Вход: \, -\begin{tabular}[c]{ |c|c|c|c|c| } - \hline a & b & a & b & \textcolor{red}{\$} \\ \hline -\end{tabular} \\ -Стек: \, -\begin{tabular}[c]{ |c|c|c|c } - \hline 0 & S & 1 & \\ \hline -\end{tabular} -\end{enumerate} -\qed -\end{example} - -\begin{example} -Пример CLR автомата. - -\begin{center} - \input{figures/GLR/CLR_example} -\end{center} -\qed -\end{example} - - -Существуют и другие модификации, например LALR(1) - -На практике конфликты стараются решать ещё и на этапе генерации. -Прикладные инструменты могут сгенерировать парсер по неоднозначной грамматике: из переноса или свёртки выбирать перенос, из нескольких свёрток --- первую в каком-то порядке (обычно в порядке появления соответствующих продукций в грамматике). - -\subsection{Сравнение классов LL и LR} - -Иерархию языков, распознаваемых различными классами алгоритмов, можно представить следующим образом. - -\begin{center} - \input{figures/GLR/LL_LR.tex} -\end{center} - -Из диаграммы видно, что класс языков, распознаваемых LL(k) алгоритмом уже, чем класс языков, распознаваемый LR(k) алгоритмом, при любом конечном $k$. Приведём несколько примеров. -\begin{enumerate} -\item $L = \{a^mb^nc \mid m \geq n \geq 0\} $ является LR(0), но для него не существует LL(1) грамматики. -\item $L = \{ a^n b^n + a^n c^n \mid n > 0\}$ является LR, но не LL. -\item Больше примеров можно найти в работе Джона Битти~\cite{BEATTY1980193}. -\end{enumerate} - -\section{GLR и его применение для КС запросов} - -Алгоритм LR довольно эффективен, однако позволяет работать не со всеми КС-грамматиками, а только с их подмножеством LR(k). Если грамматика находится за рамками допускаемого класса, некоторые ячейки управляющей таблицы могут содержать несколько значений. В этом случае грамматика отвергалась анализатором. - -Чтобы допустить множественные значения в ячейках управляющей таблицы, потребуется некоторый вид недетерминизма, который даст возможность анализатору обрабатывать несколько возможных вариантов синтаксического разбора параллельно. Именно это и предлагает анализатор Generalized LR (GLR)~\cite{tomita-1987-efficient}. Далее мы рассмотрим общий принцип работы, проиллюстрируем его с помощью примера, а также рассмотрим модификации GLR. - -\subsection{Классический GLR алгоритм} - -Впервые GLR парсер был представлен Масару Томитой в 1987~\cite{tomita-1987-efficient}. В целом, алгоритм работы идентичен LR той разницей, что управляющая таблица модифицирована таким образом, чтобы допускать множественные значения в ячейках. Интерпретатор автомата изменён соответствующим образом. - -Для того, чтобы избежать дублирования информации при обработке неоднозначностей, стоит использовать более сложную структуру стека: \textit{граф-структурированный стек} или (\textit{GSS}, Graph Structured Stack). Это направленный граф, в котором вершины соответствуют элементам стека, а ребра их соединяют по правилам управляющей таблицы. У каждой вершины может быть несколько входящих и исходящих дуг: таким образом реализуется то объединение одинаковых состяний и ветвление в случае неоднозначности. - -\begin{example} - \label{glr:example} - Рассмотрим пример GLR разбора с использованием GSS. - - Возьмем грамматику $G$ следующего вида: - \begin{align*} - &0.\quad S' \to S\$ \\ - &1.\quad S \to abC \\ - &2.\quad S \to aBC \\ - &3.\quad B \to b \\ - &4.\quad C \to c - \end{align*} - - Входное слово $ w $: - \begin{align*} - w = abc\$ - \end{align*} - - Построим для данной грамматики LR автомат: - -\begin{center} - \input{figures/GLR/GLR_example.tex} -\end{center} - - И управляющую таблицу: - - \begin{tabular}{c||c|c|c|c||c|c|c} - & a & b & c & \$ & B & C & S \\ \hline - \hline 0 & $s_2$ & & & & & 1 & \\ - \hline 1 & & & & acc & & & \\ - \hline 2 & & $s_3$ & & & 4 & & \\ - \hline 3 & & & $s_6$, $r_3$ & & & 5 & \\ - \hline 4 & & & $s_6$ & & & 7 & \\ - \hline 5 & & & & $r_1$ & & & \\ - \hline 6 & & & & $r_4$ & & & \\ - \hline 7 & & & & $r_2$ & & & - \end{tabular} - - Разберем слово $w$ с помощью алгоритма GLR. Использована следующая аннотация: вершины-состояния обозначены кругами, вершины-символы --- прямоугольниками. - \begin{enumerate} - \item Инициализируем GSS стартовым состоянием $v_0$: \\ \\ - Вход: \, - \begin{tabular}[c]{ |c|c|c|c| } - \hline a & b & c & \$ \\ \hline - \end{tabular} - \qquad GSS: \, - \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] - %uncomment if require: \path (0,306); %set diagram left start at 0, and has height of 306 - - - % Text Node - \draw [line width=0.75] (92, 109) circle [x radius= 13.6, y radius= 13.6] ; - \draw (92,109) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; - % Text Node - \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; - - - \end{tikzpicture} - \\ - - \item Видим входной символ '$a$', ищем соответствующую ему операцию в управляющей таблице --- $shift\ 2$, строим новый узел $v_1$: \\ \\ - Вход: \, - \begin{tabular}[c]{ |c|c|c|c| } - \hline \textcolor{red}{a} & b & c & \$ \\ \hline - \end{tabular} - \qquad GSS: \, - \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] - %uncomment if require: \path (0,306); %set diagram left start at 0, and has height of 306 - - - % Text Node - \draw [line width=0.75] (92, 109) circle [x radius= 13.6, y radius= 13.6] ; - \draw (92,109) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; - % Text Node - \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; - \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; - % Text Node - \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; - % Text Node - \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; - % Text Node - \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; - % Connection - \draw (138,109.84) -- (107.6,109.28) ; - \draw [shift={(105.6,109.25)}, rotate = 361.03999999999996] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (189.4,110) -- (158,110) ; - \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - - \end{tikzpicture} - \\ - - \item Повторяем для символа '$b$', операции $shift\ 3$ и узла $v_2$: \\ \\ - Вход: \, - \begin{tabular}[c]{ |c|c|c|c| } - \hline a & \textcolor{red}{b} & c & \$ \\ \hline - \end{tabular} - \qquad GSS: \, - \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] - %uncomment if require: \path (0,306); %set diagram left start at 0, and has height of 306 - - - % Text Node - \draw [line width=0.75] (92, 109) circle [x radius= 13.6, y radius= 13.6] ; - \draw (92,109) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; - % Text Node - \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; - \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {a}; - % Text Node - \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; - % Text Node - \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; - % Text Node - \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; - % Text Node - \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; - \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; - % Text Node - \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; - % Text Node - \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; - % Connection - \draw (138,109.84) -- (107.6,109.28) ; - \draw [shift={(105.6,109.25)}, rotate = 361.03999999999996] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (189.4,110) -- (158,110) ; - \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (309.4,110) -- (278,110) ; - \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (258,110) -- (218.6,110) ; - \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - - \end{tikzpicture} - \\ - - \item При обработке узла $v_3$ у нас возникает конфликт shift-reduce: $s_6,\ r_3$. Мы смотрим на вершины, смежные $v_2$, на управляющую таблицу и на правило вывода под номером 3 для поиска альтернативного построения стека. Находим $goto\ 4$ и строим вершину $v_3$ с соответствующим переходом по нетерминалу $B$ из $v_1$ (т.к. количество символов в правой части правила вывода 3 равняется 1, значит мы в дереве опустимся на глубину 1 по вершинам-состояниям):\\ \\ - Вход: \, - \begin{tabular}[c]{ |c|c|c|c| } - \hline a & b & c & \$ \\ \hline - \end{tabular} - \qquad GSS: \, - \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] - %uncomment if require: \path (0,422); %set diagram left start at 0, and has height of 422 - - - % Text Node - \draw [line width=0.75] (92, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (92,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; - % Text Node - \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; - \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; - % Text Node - \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; - % Text Node - \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; - % Text Node - \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; - % Text Node - \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; - \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; - % Text Node - \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; - % Text Node - \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; - % Text Node - \draw [line width=0.75] (258,158) -- (276,158) -- (276,182) -- (258,182) -- cycle ; - \draw (267,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {B}; - % Text Node - \draw [line width=0.75] (323, 170) circle [x radius= 13.6, y radius= 13.6] ; - \draw (323,170) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$4$}; - % Text Node - \draw (340,149) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{3}$}; - % Connection - \draw (138,110) -- (107.6,110) ; - \draw [shift={(105.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (189.4,110) -- (158,110) ; - \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (309.4,110) -- (278,110) ; - \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (258,110) -- (218.6,110) ; - \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (309.4,170) -- (278,170) ; - \draw [shift={(276,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (258,168.07) .. controls (230.15,163.58) and (213.3,149.18) .. (207.42,124.89) ; - \draw [shift={(206.99,123.01)}, rotate = 437.91] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - - \end{tikzpicture} - \\ - - \item Читаем символ '$c$' и ищем в управляющей таблице переходы из состояний 3 и 4 (так как узлы $v_2$ и $v_3$ находятся на одном уровне, то есть были построены после чтения одного символа из входного слова). Таким переходом оказывается $s_6$ в обоих случаях, поэтому соединяем узел $v_4$ с обоими рассмотренными узлами:\\ \\ - Вход: \, - \begin{tabular}[c]{ |c|c|c|c| } - \hline a & b & \textcolor{red}{c} & \$ \\ \hline - \end{tabular} - \qquad GSS: \, - \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] - %uncomment if require: \path (0,422); %set diagram left start at 0, and has height of 422 - - - % Text Node - \draw [line width=0.75] (92, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (92,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; - % Text Node - \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; - \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; - % Text Node - \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; - % Text Node - \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; - % Text Node - \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; - % Text Node - \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; - \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; - % Text Node - \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; - % Text Node - \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; - % Text Node - \draw [line width=0.75] (258,158) -- (276,158) -- (276,182) -- (258,182) -- cycle ; - \draw (267,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {B}; - % Text Node - \draw [line width=0.75] (323, 170) circle [x radius= 13.6, y radius= 13.6] ; - \draw (323,170) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$4$}; - % Text Node - \draw (340,149) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{3}$}; - % Text Node - \draw [line width=0.75] (374,98) -- (392,98) -- (392,122) -- (374,122) -- cycle ; - \draw (383,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; - % Text Node - \draw [line width=0.75] (374,158) -- (392,158) -- (392,182) -- (374,182) -- cycle ; - \draw (383,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; - % Text Node - \draw [line width=0.75] (437, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$6$}; - % Text Node - \draw (450,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{4}$}; - % Connection - \draw (138,110) -- (107.6,110) ; - \draw [shift={(105.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (189.4,110) -- (158,110) ; - \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (309.4,110) -- (278,110) ; - \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (258,110) -- (218.6,110) ; - \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (309.4,170) -- (278,170) ; - \draw [shift={(276,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (258,168.07) .. controls (230.15,163.58) and (213.3,149.18) .. (207.42,124.89) ; - \draw [shift={(206.99,123.01)}, rotate = 437.91] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (374,110) -- (338.6,110) ; - \draw [shift={(336.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,110) -- (394,110) ; - \draw [shift={(392,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (435.82,123.55) .. controls (435.9,150.31) and (416.89,165.24) .. (393.78,168.34) ; - \draw [shift={(392,168.55)}, rotate = 353.9] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (374,170) -- (338.6,170) ; - \draw [shift={(336.6,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - - \end{tikzpicture} - \\ - - \item При обработке узла $v_4$ находим соответствующею 6-ому состоянию редукцию по правилу 4. Его правая часть содержит один символ '$c$', 2 вершины-символа с которым достижимы из $v_4$. Находим вершины-состояния, которые смежны с этими вершинами-символами и обрабатываем переходы по левой части правила 4. Такими переходами по нетерминалу $C$ оказываются $5$ и $7$. Строим соответствующие им вершины $v_5$ и $v_6$:\\ \\ - Вход: \, - \begin{tabular}[c]{ |c|c|c|c| } - \hline a & b & c & \$ \\ \hline - \end{tabular} - \qquad GSS: \, - \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] - %uncomment if require: \path (0,422); %set diagram left start at 0, and has height of 422 - - - % Text Node - \draw [line width=0.75] (92, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (92,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; - % Text Node - \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; - \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; - % Text Node - \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; - % Text Node - \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; - % Text Node - \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; - % Text Node - \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; - \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; - % Text Node - \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; - % Text Node - \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; - % Text Node - \draw [line width=0.75] (258,158) -- (276,158) -- (276,182) -- (258,182) -- cycle ; - \draw (267,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {B}; - % Text Node - \draw [line width=0.75] (323, 170) circle [x radius= 13.6, y radius= 13.6] ; - \draw (323,170) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$4$}; - % Text Node - \draw (340,149) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{3}$}; - % Text Node - \draw [line width=0.75] (374,98) -- (392,98) -- (392,122) -- (374,122) -- cycle ; - \draw (383,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; - % Text Node - \draw [line width=0.75] (374,158) -- (392,158) -- (392,182) -- (374,182) -- cycle ; - \draw (383,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; - % Text Node - \draw [line width=0.75] (437, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$6$}; - % Text Node - \draw (450,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{4}$}; - % Text Node - \draw [line width=0.75] (372,38) -- (392,38) -- (392,62) -- (372,62) -- cycle ; - \draw (382,50) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; - % Text Node - \draw [line width=0.75] (372,218) -- (392,218) -- (392,242) -- (372,242) -- cycle ; - \draw (382,230) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; - % Text Node - \draw [line width=0.75] (437, 50) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,50) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$5$}; - % Text Node - \draw [line width=0.75] (437, 231) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,231) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$7$}; - % Text Node - \draw (452,28) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{5}$}; - % Text Node - \draw (452,208) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{6}$}; - % Connection - \draw (138,110) -- (107.6,110) ; - \draw [shift={(105.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (189.4,110) -- (158,110) ; - \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (309.4,110) -- (278,110) ; - \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (258,110) -- (218.6,110) ; - \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (309.4,170) -- (278,170) ; - \draw [shift={(276,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (258,168.07) .. controls (230.15,163.58) and (213.3,149.18) .. (207.42,124.89) ; - \draw [shift={(206.99,123.01)}, rotate = 437.91] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (374,110) -- (338.6,110) ; - \draw [shift={(336.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,110) -- (394,110) ; - \draw [shift={(392,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (435.82,123.55) .. controls (435.9,150.31) and (416.89,165.24) .. (393.78,168.34) ; - \draw [shift={(392,168.55)}, rotate = 353.9] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (374,170) -- (338.6,170) ; - \draw [shift={(336.6,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (372,50.52) .. controls (341.88,50.18) and (326.06,64.88) .. (324.53,94.64) ; - \draw [shift={(324.46,96.48)}, rotate = 271.78] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (372,229.65) .. controls (341.88,230.53) and (326.05,215.79) .. (324.5,185.41) ; - \draw [shift={(324.42,183.53)}, rotate = 448.21] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,50) -- (394,50) ; - \draw [shift={(392,50)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,230.75) -- (394,230.22) ; - \draw [shift={(392,230.18)}, rotate = 361.03999999999996] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - - \end{tikzpicture} - \\ - - \item При обработке узлов $v_5$ и $v_6$ находим редукции с символом '$S$' в левой части и тремя символами в правой. Возвращаемся на 3 вершины-состояния назад и строим вершину $v_7$ с переходом по $S$: \\ \\ - Вход: \, - \begin{tabular}[c]{ |c|c|c|c| } - \hline a & b & c & \$ \\ \hline - \end{tabular} - \qquad GSS: \, - \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] - %uncomment if require: \path (0,422); %set diagram left start at 0, and has height of 422 - - - % Text Node - \draw [line width=0.75] (92, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (92,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; - % Text Node - \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; - \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; - % Text Node - \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; - % Text Node - \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; - % Text Node - \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; - % Text Node - \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; - \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; - % Text Node - \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; - % Text Node - \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; - % Text Node - \draw [line width=0.75] (258,158) -- (276,158) -- (276,182) -- (258,182) -- cycle ; - \draw (267,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {B}; - % Text Node - \draw [line width=0.75] (323, 170) circle [x radius= 13.6, y radius= 13.6] ; - \draw (323,170) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$4$}; - % Text Node - \draw (340,149) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{3}$}; - % Text Node - \draw [line width=0.75] (374,98) -- (392,98) -- (392,122) -- (374,122) -- cycle ; - \draw (383,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; - % Text Node - \draw [line width=0.75] (374,158) -- (392,158) -- (392,182) -- (374,182) -- cycle ; - \draw (383,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; - % Text Node - \draw [line width=0.75] (437, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$6$}; - % Text Node - \draw (450,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{4}$}; - % Text Node - \draw [line width=0.75] (372,38) -- (392,38) -- (392,62) -- (372,62) -- cycle ; - \draw (382,50) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; - % Text Node - \draw [line width=0.75] (372,218) -- (392,218) -- (392,242) -- (372,242) -- cycle ; - \draw (382,230) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; - % Text Node - \draw [line width=0.75] (437, 50) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,50) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$5$}; - % Text Node - \draw [line width=0.75] (437, 231) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,231) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$7$}; - % Text Node - \draw (452,28) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{5}$}; - % Text Node - \draw (452,208) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{6}$}; - % Text Node - \draw [line width=0.75] (373,278) -- (391,278) -- (391,302) -- (373,302) -- cycle ; - \draw (382,290) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {S}; - % Text Node - \draw [line width=0.75] (437, 290) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,290) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$1$}; - % Text Node - \draw (452,268) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{7}$}; - % Connection - \draw (138,110) -- (107.6,110) ; - \draw [shift={(105.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (189.4,110) -- (158,110) ; - \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (309.4,110) -- (278,110) ; - \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (258,110) -- (218.6,110) ; - \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (309.4,170) -- (278,170) ; - \draw [shift={(276,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (258,168.07) .. controls (230.15,163.58) and (213.3,149.18) .. (207.42,124.89) ; - \draw [shift={(206.99,123.01)}, rotate = 437.91] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (374,110) -- (338.6,110) ; - \draw [shift={(336.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,110) -- (394,110) ; - \draw [shift={(392,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (435.82,123.55) .. controls (435.9,150.31) and (416.89,165.24) .. (393.78,168.34) ; - \draw [shift={(392,168.55)}, rotate = 353.9] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (374,170) -- (338.6,170) ; - \draw [shift={(336.6,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (372,50.52) .. controls (341.88,50.18) and (326.06,64.88) .. (324.53,94.64) ; - \draw [shift={(324.46,96.48)}, rotate = 271.78] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (372,229.65) .. controls (341.88,230.53) and (326.05,215.79) .. (324.5,185.41) ; - \draw [shift={(324.42,183.53)}, rotate = 448.21] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,50) -- (394,50) ; - \draw [shift={(392,50)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,230.75) -- (394,230.22) ; - \draw [shift={(392,230.18)}, rotate = 361.03999999999996] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,290) -- (393,290) ; - \draw [shift={(391,290)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (373,289.72) .. controls (234.96,286.59) and (143.34,231.38) .. (98.15,124.08) ; - \draw [shift={(97.47,122.46)}, rotate = 427.47] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - - \end{tikzpicture} - \\ - \item Наконец, обрабатывая вершину $v_7$, читаем символ '$\$$' и строим узел $v_8$, который соответствует допускающим состоянием: \\ \\ - Вход: \, - \begin{tabular}[c]{ |c|c|c|c| } - \hline a & b & c & \textcolor{red}{\$} \\ \hline - \end{tabular} - \qquad GSS: \, - \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] - %uncomment if require: \path (0,422); %set diagram left start at 0, and has height of 422 - - - % Text Node - \draw [line width=0.75] (92, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (92,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; - % Text Node - \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; - \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; - % Text Node - \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; - % Text Node - \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; - % Text Node - \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; - % Text Node - \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; - \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; - % Text Node - \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; - % Text Node - \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; - % Text Node - \draw [line width=0.75] (258,158) -- (276,158) -- (276,182) -- (258,182) -- cycle ; - \draw (267,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {B}; - % Text Node - \draw [line width=0.75] (323, 170) circle [x radius= 13.6, y radius= 13.6] ; - \draw (323,170) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$4$}; - % Text Node - \draw (340,149) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{3}$}; - % Text Node - \draw [line width=0.75] (374,98) -- (392,98) -- (392,122) -- (374,122) -- cycle ; - \draw (383,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; - % Text Node - \draw [line width=0.75] (374,158) -- (392,158) -- (392,182) -- (374,182) -- cycle ; - \draw (383,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; - % Text Node - \draw [line width=0.75] (437, 110) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$6$}; - % Text Node - \draw (450,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{4}$}; - % Text Node - \draw [line width=0.75] (372,38) -- (392,38) -- (392,62) -- (372,62) -- cycle ; - \draw (382,50) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; - % Text Node - \draw [line width=0.75] (372,218) -- (392,218) -- (392,242) -- (372,242) -- cycle ; - \draw (382,230) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; - % Text Node - \draw [line width=0.75] (437, 50) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,50) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$5$}; - % Text Node - \draw [line width=0.75] (437, 231) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,231) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$7$}; - % Text Node - \draw (452,28) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{5}$}; - % Text Node - \draw (452,208) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{6}$}; - % Text Node - \draw [line width=0.75] (373,278) -- (391,278) -- (391,302) -- (373,302) -- cycle ; - \draw (382,290) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {S}; - % Text Node - \draw [line width=0.75] (437, 290) circle [x radius= 13.6, y radius= 13.6] ; - \draw (437,290) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$1$}; - % Text Node - \draw (452,268) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{7}$}; - % Text Node - \draw [line width=0.75] (488,278) -- (506,278) -- (506,302) -- (488,302) -- cycle ; - \draw (497,290) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {\$}; - % Text Node - \draw [line width=0.75] (557, 290) circle [x radius= 17.8, y radius= 17.8] ; - \draw (557,290) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {acc}; - % Text Node - \draw (575,262) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{8}$}; - % Connection - \draw (138,110) -- (107.6,110) ; - \draw [shift={(105.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (189.4,110) -- (158,110) ; - \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (309.4,110) -- (278,110) ; - \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (258,110) -- (218.6,110) ; - \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (309.4,170) -- (278,170) ; - \draw [shift={(276,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (258,168.07) .. controls (230.15,163.58) and (213.3,149.18) .. (207.42,124.89) ; - \draw [shift={(206.99,123.01)}, rotate = 437.91] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (374,110) -- (338.6,110) ; - \draw [shift={(336.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,110) -- (394,110) ; - \draw [shift={(392,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (435.82,123.55) .. controls (435.9,150.31) and (416.89,165.24) .. (393.78,168.34) ; - \draw [shift={(392,168.55)}, rotate = 353.9] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (374,170) -- (338.6,170) ; - \draw [shift={(336.6,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (372,50.52) .. controls (341.88,50.18) and (326.06,64.88) .. (324.53,94.64) ; - \draw [shift={(324.46,96.48)}, rotate = 271.78] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (372,229.65) .. controls (341.88,230.53) and (326.05,215.79) .. (324.5,185.41) ; - \draw [shift={(324.42,183.53)}, rotate = 448.21] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,50) -- (394,50) ; - \draw [shift={(392,50)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,230.75) -- (394,230.22) ; - \draw [shift={(392,230.18)}, rotate = 361.03999999999996] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (423.4,290) -- (393,290) ; - \draw [shift={(391,290)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (373,289.72) .. controls (234.96,286.59) and (143.34,231.38) .. (98.15,124.08) ; - \draw [shift={(97.47,122.46)}, rotate = 427.47] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (488,290) -- (452.6,290) ; - \draw [shift={(450.6,290)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - % Connection - \draw (539.2,290) -- (508,290) ; - \draw [shift={(506,290)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; - - - \end{tikzpicture} - \\ - \end{enumerate} - - - -\end{example} - -\subsection{Модификации GLR} -Алгоритм, представленный Томитой имел большой недостаток: он корректно работал не со всеми КС грамматиками, хоть и расширял класс допустимых LR анализаторами. Объем потребляемой памяти классическим GLR можно оценить как $ O(n^3)$ с учетом оптимизаций, о которых говорилось ранее. - -Спустя некоторое время после публикации Томита-парсера, Элизабет Скотт и Эндриан Джонстоун представили $RNGLR$ (Right Nulled GLR)~\cite{Scott:2006:RNG:1146809.1146810} --- модифицированная версия GLR, которая решала проблему скрытых рекурсий. Это позволило расширить класс допускаемых грамматик до КС. Однако объем потребляемой памяти можно оценить сверху уже полиномом $O(n^{k+1})$, где k --- длина самого длинного правила грамматики, что несколько ухудшило оценку классического GLR. - -С этой проблемой справился BRNGLR (Binary RNGLR)~\cite{Scott:2007:BCT:1289813.1289815}. За счет бинаризации удалось получить кубическую оценку сложности и при этом также, как и RNGLR, допускать все КС грамматики. - -Подробное описание разных вариаций и история: PhD~\cite{Economopoulos2006GeneralisedLP} - -Кроме того, GLR довольно естесственно обобщается до решения задачи поиска путей с КС ограничениями. Это происходит следующим образом: элементами во входной структуре теперь будем считать не позиции символа в слове, а вершины графа (то есть ``позици'' и множество смежных вершин). Это приводит к тому, что при применении операции shift, следующих символов может быть несколько и каждый из них должен быть рассмотрен отдельно, сдвигаясь по соответствующему ребру и проходя входной граф в ширину. Подробное описание алгоритма и псевдокод представлены в работе~\cite{10.1007/978-3-319-41579-6_22}. - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item Постройте LR автомат и управляющую таблицу для грамматики $G_1$: $S \to a S b$; $S \to \epsilon$. -% \item Постройте LR автомат и управляющую таблицу для грамматики $G_2$: $S \to S S S$; $S \to S S$; $S \to a$. -% \item Проведите GLR разбор для грамматики $G_2$ и входного слова $w = aaa\$$. -% \item Реализуйте LR анализатор на любом языке программирования. Программа должна принимать на вход файл с однозначной грамматикой и входное слово, строить LR автомат и управляющую таблицу (во внутреннем представлении), и сообщать, выводимо ли входное слово в данной грамматике. -% \item[6*.] Реализуйте GLR анализатор на любом языке программирования. Программа должна принимать на вход файл с однозначной грамматикой и входное слово, работать согласно алгоритму GLR и сохранять GSS, а также сообщать, выводимо ли входное слово в данной грамматике. -%\end{enumerate} diff --git a/tex/GraphTheoryIntro.tex b/tex/GraphTheoryIntro.tex deleted file mode 100644 index 3823810..0000000 --- a/tex/GraphTheoryIntro.tex +++ /dev/null @@ -1,538 +0,0 @@ -\chapter{Некоторые сведения из теории графов}\label{chpt:GraphTheoryIntro} - -В данном разделе мы дадим определения базовым понятиям из теории графов, рассмотрим несколько классических задач из области анализа графов и алгоритмы их решения. -Кроме этого, поговорим о связи между линейной алгеброй и некоторыми задачами анализа графов. -Всё это понадобится нам при последующей работе. - -\section{Основные определения} - -\begin{definition} - \textit{Помеченный ориентированный граф} $\mathcal{G} = \langle V, E, L \rangle$, где $V$ --- конечное множество вершин, $E$ --- конечное множество рёбер, т.ч. $E \subseteq V \times L \times V$, $L$ --- конечное множество меток на рёбрах. В некоторых случаях метки называют \textit{весами}\footnote{Весами метки называют, как правило, тогда, когда они берутся из какого-либо поля, например $\mathbb{R}$ или $\mathbb{N}$.} и тогда говорят о \textit{взвешенном} графе. -\end{definition} - - -\begin{definition} - В случае, если для любого ребра $(u,l,v)$ в графе также содержится ребро $(v,l,u)$, говорят, что граф \textit{неориентированный}. -\end{definition} - - -В дальнейшем речь будет идти о конечных ориентированных помеченных графах. -Мы будем использовать термин \textit{граф} подразумевая именно конечный ориентированный помеченный граф, если только не оговорено противное. - -Также мы будем считать, что все вершины занумерованы подряд с нуля. -То есть можно считать, что $V$ --- это отрезок $[0, |V| - 1]$ неотрицательных целых чисел, где $|V|$ --- мощность множества $V$. - -\begin{example}[Пример графа и его графического представления] - Пусть дан граф - \begin{align*} - \mathcal{G} = \langle V&=\{0,1,2,3\},\\ - E&=\{(0,a,1), (1,a,2), (2,a,0), (2,b,3), (3,b,2)\}, \\ - L&=\{a,b\} \rangle. - \end{align*} - - Графическое представление графа $\mathcal{G}$: - \begin{center} - \input{figures/graph/graph0} - \end{center} -\end{example} - -\begin{example}[Пример рёбер графа] -$(0,a,1)$ и $(3,b,2)$ --- это рёбра графа $\mathcal{G}_1$. При этом $(3,b,2)$ $(2,b,3)$ --- это разные рёбра. -\end{example} - -\begin{definition} - \textit{Путём} $\pi$ в графе $\mathcal{G}$ будем называть последовательность рёбер такую, что для любых двух последовательных рёбер $e_1=(u_1,l_1,v_1)$ и $e_2=(u_2,l_2,v_2)$ в этой последовательности, конечная вершина первого ребра является начальной вершиной второго, то есть $v_1 = u_2$. Будем обозначать путь из вершины $v_0$ в вершину $v_n$ как $v_0 \pi v_n$. Иными совами, $$v_0 \pi v_n = e_0,e_1, \dots, e_{n-1} = (v_0, l_0, v_1),(v_1,l_1,v_2),\dots,(v_{n-1},l_{n-1},v_n).$$ - - Часто для представления пути мы буем использовать следующие нотации: -\begin{center} - \input{figures/graph/path0.tex} -\end{center} -\end{definition} - или -$$ -v_0 \xrightarrow[]{l_0} v_1 \xrightarrow[]{l_1} v_2 \xrightarrow[]{l_2} \ldots \xrightarrow[]{l_{n-2}} v_{n-1} \xrightarrow[]{l_{n-1}} v_n. -$$ - -\begin{example}[Пример путей графа] -$(0,a,1),(1,a,2) = 0\pi_1 2$ --- путь из вершины 0 в вершину 2 в графе $\mathcal{G}_1$. -При этом $(0,a,1),(1,a,2),(2,b,3),(3,b,2) = 0\pi_2 2$ --- это тоже путь из вершины 0 в вершину 2 в графе $\mathcal{G}_1$, но он не равен $0\pi_1 2$. -\end{example} - -Кроме того, нам потребуется отношение, отражающее факт существования пути между двумя вершинами. - -\begin{definition}\label{def:reach} - \textit{Отношение достижимости} в графе: - $(v_i,v_j) \in P \iff \exists v_i \pi v_j$. -\end{definition} - -Отметим, что в некоторых задачах удобно считать по умолчанию, что $(v_i,v_i) \in P$, однако наше определение такого не допускает. Исправить ситуацию можно явно добавив петли $(v_i,l,v_i)$ для всех вершин. - -Один из способов задать граф --- это задать его \textit{матрицу смежности}. - -\begin{definition} - \textit{Матрица смежности} графа $\mathcal{G}=\langle V,E,L \rangle$ --- это квадратная матрица $M$ размера $n \times n$, где $|V| = n$, построенная над коммутативным моноидом $\mathbb{G} = (S,\circ\colon S \times S \to S)$, который конструируется следующим образом. - - \begin{enumerate} - \item $L \subseteq S$. - \item $\circ$ --- коммутативная бинарная операция. - \item Существует $ \mathbb{0} \in (S \setminus L)$ --- нейтральный элемент относительно $\circ$. - \end{enumerate} - - При этом $M[i,j] = \bigcirc_{(i,l,j) \in E}l$, где $\bigcirc_\varnothing = \mathbb{0}$. -\end{definition} - -Заметим, что наше определение матрицы смежности отличается от классического, в котором матрица является булевой и отражает лишь факт наличия хотя бы одного ребра. То есть $M[i,j] = 1 \iff \exists e = (i,\_,j) \in E$. - -\begin{example}[Пример матрицы смежности неориентированного графа]\label{exmpl:undirectedGraphMatrix} - Пусть дан следующий неориентированный граф. - \begin{center} - \input{figures/graph/graph1.tex} - \end{center} - -$\mathbb{G} = (S,\circ)$ в этом случае конструируется следующим образом. Во-первых, придётся предположить, что $L$ --- множество с одним элементом, скажем $s$, и считать, что все рёбра помечены им\footnote{А раз все рёбра имеют одинаковый заранее известный вес, то можно его и не писать для каждого ребра при задании графа. Поэтому привычное нам изображение получается достаточно логичным.}. Далее, $S = L \cup{\{n\}} = \{s,n\}$, где $n$ --- нейтральный элемент относительно $\circ$. Тогда $\circ$ можно определить поточечно следующим образом. -\begin{itemize} - \item $s \circ s = s$ - \item $s \circ n = n \circ s = s$ - \item $n \circ n = n$ -\end{itemize} - -Таким образом, матрица смежности данного графа выглядит следующим образом: -$$ -\begin{pmatrix} - n & s & s & n \\ - s & n & s & n \\ - s & s & n & s \\ - n & n & s & n -\end{pmatrix} -$$ -, что может показаться несколько непривычным. Однако заметим, что построенная нами структура $\mathbb{G} = (\{s,n\}, \circ)$ изоморфна $\mathbb{G}' = (\{1,0\}, \vee)$. При переходе к $\mathbb{G}'$ мы получим привычную нам булеву матрицу смежности: - $$ - \begin{pmatrix} - 0 & 1 & 1 & 0 \\ - 1 & 0 & 1 & 0 \\ - 1 & 1 & 0 & 1 \\ - 0 & 0 & 1 & 0 - \end{pmatrix} - $$ - Заметим, что матрица смежности неориентированного графа всегда симметрична относительно главной диагонали. -\end{example} - -\begin{example}[Пример матрицы смежности ориентированного графа]\label{example:diGraph} - Дан ориентированный граф: - \begin{center} - \input{figures/graph/graph2.tex} - \end{center} - - Построить его булеву матрицу смежности можно применив рассуждения из предыдущего примера (\ref{exmpl:undirectedGraphMatrix}) и выглядеть она будет следующим образом: - $$ - \begin{pmatrix} - 0 & 1 & 0 & 0 \\ - 0 & 0 & 1 & 0 \\ - 1 & 0 & 0 & 1 \\ - 0 & 0 & 1 & 0 - \end{pmatrix} - $$ -\end{example} - -\begin{example}[Пример матрицы смежности помеченного графа] - Пусть дан следующий помеченный граф. - \begin{center} - \input{figures/graph/graph3.tex} - \end{center} - - В данном случае $L = \{\{a\},\{b\}\}$, а $\mathbb{G} = ( \{\{a\},\{b\},\{a,b\},\varnothing\} ,\cup)$, где $\varnothing$ --- нейтральный элемент. - Тогда матрица матрица смежности исходного графа выглядит следующим образом: - $$ - \begin{pmatrix} - \varnothing & \{a\} & \varnothing & \varnothing \\ - \varnothing & \varnothing & \{a\} & \varnothing \\ - \{a\} & \varnothing & \varnothing & \{a,b\} \\ - \varnothing & \varnothing & \{b\} & \varnothing - \end{pmatrix} - $$ -\end{example} - -Необходимо заметить, что свойства структуры $\mathbb{G}$, а значит и детали её построения, зависят от задачи, в рамках которой рассматривается граф. В примерах выше мы строили $\mathbb{G}$ из некоторых общих соображений, не специфицируя решаемую задачу, стараясь получить ожидаемый результат. Далее мы рассмотрим пример, в котором видно, как решаемая задача влияет на построение $\mathbb{G}$. - -\begin{example}[Пример матрицы смежности взвешенного графа]\label{example:apspGraph} - Пусть дан следующий взвешенный граф: - \begin{center} - \input{figures/graph/graph4.tex} - \end{center} - - Будем считать, что веса берутся из $\mathbb{R}$, а решаемая задача --- поиск кратчайших путей между вершинами. В таком случае естественно предположить, что для любой вершины $v_i$ существует петля $(v_i,0,v_i)$, хоть она явно и не изображена. Далее, $\mathbb{G} = ( \mathbb{R}\cup \{\infty\} , \min)$, где $\infty$ --- нейтральный элемент относительно операции $\min$. - - В результате мы получим следующую матрицу смежности: - $$ - \begin{pmatrix} - 0 & -1.4 & \infty & \infty \\ - \infty & 0 & 2.2 & \infty \\ - 0.5 & \infty & 0 & 1.85 \\ - \infty & \infty & -0.76 & 0 - \end{pmatrix} - $$ -\end{example} - -Таким образом, уже можно заметить, что введение моноида как абстракции позволяет достаточно унифицированным образом смотреть на различные графы и их матрицы смежности. Далее мы увидим, что данный путь позволит решать унифицированным образом достаточно широкий круг задач, связанных с анализом путей в графах. Но сперва мы сформулируем различные варианты задачи поиска путей в графе. % Это необходимо для формулировки задач, на решение которых мы в конечном итоге нацелены. - - -\section{Обход графа в ширину} - -Обход графа в ширину (Breadth-First Search, BFS) --- это одна из фундаментальных задач анализа графов, для решения которой существует соответствующий алгоритм, изложенный в классической литературе (подробнее, например, в~\cite{} или ~\cite{}). -Данный алгоритм является основой для многих алгоритмов поиска в графе. - -В общих чертах, задача заключается в том, чтобы начиная с некоторой заданной вершины графа (источника) обойти все достижимые из неё вершины в некотором порядке. -Шаг --- просмотр все смежных. И так для всего фронта. Главное не посещать одну и ту же вершину несколько раз. - -Псевдокод классического алгоритма - -Пример. - -Алгоритм обхода в ширину может быть переформулирован в терминах матрично-векторных операций следующим образом\footnote{ -Стоит отметить, что ситуация с не менее известным обходом в глубину (Depth-First Search, DFS) более сложная: -на момент написания текста не известно естественного выражения данного обхода в терминах линейной алгебры. -Доказательство невозможности такого построения также не предъявлены. -При этом, решения для частных случаев (деревья, ориентированные графы без циклов) предложены, например, в работе~\cite{10.1145/3315454.3329962}.}. -Пусть фронт --- вектор размера $n$, а сам граф представлен матрицей смежности. -Тогда один шаг --- получение нового фронта --- это умножение текущего фронта на матрицу смежности. -Для того, чтобы отслеживать посещённые вершины нужна маска. - -Псевдокод алгоритма на ЛА - -\begin{example} - - Рассмотрим обход в ширину графа из примера~\ref{example:diGraph} начиная с вершины 2. - Для обозначения текущего фронта будем использовать зелёный цвет, а для достижимых из него за один шаг --- жёлтый, обведём вершину красным, если она посешается повторно. - -\begin{tabular}[t]{c | c} - \begin{minipage}[c]{0.35\textwidth} - \input{figures/graph/graph_BFS_1.tex} - \end{minipage} - & - \begin{minipage}{0.7\textwidth} - $\begin{aligned} - \textit{current\_front} & = - \begin{pmatrix} - 0 & 0 & 1 & 0 - \end{pmatrix} - \\ - \textit{visited} & = - \begin{pmatrix} - 0 & 0 & 0 & 0 - \end{pmatrix} - \\ - \textit{new\_front} & = - \textit{current\_front} \cdot M - \\ - & = - \begin{pmatrix} - 0 & 0 & 1 & 0 - \end{pmatrix} - \begin{pmatrix} - 0 & 1 & 0 & 0 \\ - 0 & 0 & 1 & 0 \\ - 1 & 0 & 0 & 1 \\ - 0 & 0 & 1 & 0 - \end{pmatrix} \\ - & = - \begin{pmatrix} - 1 & 0 & 0 & 1 - \end{pmatrix} - \\ - \textit{visited} & = \textit{visited} \textit{new\_front} \\ - &= - \begin{pmatrix} - 0 & 0 & 0 & 0 - \end{pmatrix} - \begin{pmatrix} - 0 & 0 & 1 & 0 - \end{pmatrix} - \\ - \textit{current\_front} & = \textit{visited} \textit{new\_front} - \\ - & = - \begin{pmatrix} - 1 & 0 & 0 & 1 - \end{pmatrix} - \begin{pmatrix} - 0 & 0 & 1 & 0 - \end{pmatrix} \\ - & = - \begin{pmatrix} - 1 & 0 & 0 & 1 - \end{pmatrix} \\ - \end{aligned}$ - \end{minipage} - \\ \hline - \begin{minipage}[c]{0.35\textwidth} - \input{figures/graph/graph_BFS_2.tex} - \end{minipage} - & - $\begin{aligned} - & \begin{pmatrix} - 1 & 0 & 0 & 1 - \end{pmatrix} - \begin{pmatrix} - 0 & 1 & 0 & 0 \\ - 0 & 0 & 1 & 0 \\ - 1 & 0 & 0 & 1 \\ - 0 & 0 & 1 & 0 - \end{pmatrix} \\ &= - \begin{pmatrix} - 0 & 1 & 1 & 0 - \end{pmatrix} -\end{aligned}$ - \\ \hline - \begin{minipage}[c]{0.35\textwidth} - \input{figures/graph/graph_BFS_3.tex} - \end{minipage} - & - $ - \begin{pmatrix} - 0 & 1 & 0 & 0 - \end{pmatrix} - \begin{pmatrix} - 0 & 1 & 0 & 0 \\ - 0 & 0 & 1 & 0 \\ - 1 & 0 & 0 & 1 \\ - 0 & 0 & 1 & 0 - \end{pmatrix} = - \begin{pmatrix} - 0 & 0 & 1 & 0 - \end{pmatrix} - $ -\end{tabular} - -\end{example} - - -multiple-source BFS. Тот же обход в ширину, только источников несколько и надо помнить, какая из вершин из какого источника достижима. Постановка задачи. Решение через линейную алгебру~\cite{9286186} Уже не вектор, а матрица: храним информацию про каждую стартовую вершину отдельно. - -Псевдокод алгоритма на ЛА - -Пример. - -\begin{minipage}[c]{0.35\textwidth} - \input{figures/graph/graph_MS-BFS_1.tex} -\end{minipage} -\begin{minipage}{0.7\textwidth} -\end{minipage} - - -\begin{minipage}[c]{0.35\textwidth} - \input{figures/graph/graph_MS-BFS_2.tex} -\end{minipage} -\begin{minipage}{0.7\textwidth} -\end{minipage} - - -\section{Задачи поиска путей} - -Одна из классических задач анализа графов --- это задача поиска путей между вершинами с различными ограничениями. - -При этом возможны различные постановки задачи. -С одной стороны, постановки различаются тем, что именно мы хотим получить в качестве результата. Здесь наиболее частыми являются следующие варианты. - -\begin{itemize} -\item Наличие хотя бы одного пути, удовлетворяющего ограничениям, в графе. В данном случае не важно, между какими вершинами существует путь, важно лишь наличие его в графе. - -\item Наличие пути, удовлетворяющего ограничениям, между некоторыми вершинами: задача достижимости. - При данной постановке задачи, нас интересует ответ на вопрос достижимости вершины $v_i$ из вершины $v_j$ по пути, удовлетворяющему ограничениям. - Такая постановка требует лишь проверить существование пути, но не его предоставления в явном виде. - -\item Поиск одного пути, удовлетворяющего ограничениям: необходимо не только установить факт наличия пути, но и предъявить его. При этом часто подразумевается, что возвращается любой путь, являющийся решением, без каких-либо дополнительных ограничений. Хотя, например, в некоторых задачах дополнительное требование простоты или наименьшей длины выглядит достаточно естественным. - -\item Поиск всех путей: необходимо предоставить все пути, удовлетворяющие заданным ограничениям. -\end{itemize} - -С другой стороны, задачи могут различаться ещё и тем, как фиксируются множества стартовых и конечных вершин. -Здесь возможны следующие варианты: -\begin{itemize} -\item от одной вершины до всех, -\item между всеми парами вершин, -\item между фиксированной парой вершин, -\item между двумя множествами вершин $V_1$ и $V_2$, что подразумевает решение задачи для всех $(v_i,v_j) \in V_1 \times V_2$. -\end{itemize} - -Стоит отметить, что последний вариант является самым общим и остальные --- лишь его частные случаи. -Однако этот вариант часто выделяют отдельно, подразумевая, что остальные, выделенные, варианты в него не включаются. - -В итоге, перебирая возможные варианты желаемого результата и способы фиксации стартовых и финальных вершин, мы можем сформулировать достаточно большое количество задач. Например, задачу поиска всех путей между двумя заданными вершинами, задачу поиска одного пути от фиксированной стартовой вершины до каждой вершины в графе, или задачу достижимости между всеми парами вершин. - -Часто поиск путей сопровождается изучением их свойств, что далее приводит к формулированию дополнительных ограничений на пути в терминах этих свойств. Например, можно потребовать, чтобы пути были простыми или не проходили через определённые вершины. Один из естественных способов описывать свойства и, как следствие, задавать ограничения --- это использовать ту алгебраическую структуру, из которой берутся веса рёбер графа\footnote{На самом деле здесь наблюдается некоторая двойственность. С одной стороны, действительно, удобно считать, что свойства описываются в терминах некоторой заданной алгебраической структуры. Но, вместе с этим, структура подбирается исходя из решаемой задачи.}. - -Предположим, что дан граф $\mathcal{G} = \langle V, E, L\rangle $, где $L = \langle S, \oplus, \otimes \rangle$ --- это полукольцо. Тогда изучение свойств путей можно описать следующим образом: -\begin{equation} \label{eq:algPathProblem} - \{(v_i, v_j, c) \mid \exists v_i \pi v_j, c = \bigoplus_{\forall v_i \pi v_j} \bigotimes_{(u,l,v) \in \pi } l \}. -\end{equation} - -Иными словами, для каждой пары вершин, для которой существует хотя бы один путь, их соединяющий, мы агрегируем (с помощью операции $\oplus$ из полукольца) информацию обо всех путях между этими вершинами. При этом информация о пути получается как свёртка меток рёбер пути с использованием операции $\otimes$\footnote{Заметим, что детали свёртки вдоль пути зависят от свойств полукольца (и от решаемой задачи). Так, если полукольцо коммутативно, то нам не обязательно соблюдать порядок рёбер. В дальнейшем мы увидим, что данные особенности полукольца существенно влияют на особенности алгоритмов решения соответствующих задач.}. - -Естественным требованием (хотя бы для прикладных задач, решаемых таким способом) является существование и конечность указанной суммы. На данном этапе мы не будем касаться того, какие именно свойства полукольца могут нам обеспечить данное свойство, однако в дальнейшем будем считать, что оно выполняется. Более того, будем стараться приводить частные для конкретной задачи рассуждения, показывающие, почему это свойство выполняется в рассматриваемых в задаче ограничениях. - -Описанная выше задача общего вида называется анализом свойств путей алгебраическими методами (Algebraic Path Problem~\cite{Baras2010PathPI}) и предоставляет общий способ для решения широкого класса прикладных задач\footnote{В работе ``Path Problems in Networks''~\cite{Baras2010PathPI} собран действительно большой список прикладных задач с описанием соответствующих полуколец. Сводная таблица на страницах 58--59 содержит 29 различных прикладных задач и соответствующих полуколец.}. Наиболее известными являются такие задачи, как построение транзитивного замыкания графа и поиск кратчайших путей (All PAirs Shortest Path или APSP). Далее мы подробнее обсудим эти две задачи и предложим алгоритмы их решения. - - -\section{Алгоритм Флойда-Уоршелла} - -Наиболее естественным образом решение обсуждаемых выражается в терминах операций над матрицей смежности исходного графа. Поэтому предположим, что исходный граф задан матрицей над моноидом $\mathbb{G} = (S,\oplus)$. - -Как мы видели ранее, операция $\oplus$ позволяет нам агрегировать информацию по всем параллельным рёбрам. Ровно она же и будет агрегировать информацию по всем путям между двумя вершинами\footnote{Вообще говоря, работая с матрицей смежности мы не видим разницу между путём и ребром, так как любая запись в матрице смежности в ячейке $[i,j]$ говорит нам только о том, что вершины $i$ и $j$ связаны и эта связь обладает некоторым свойством (значение в ячейке), и ничего не говорит о том, как эта связь устроена.}. Таким образом, осталось сконструировать операцию, отвечающую за агрегацию информации вдоль пути. Здесь мы будем исходить из того, что новый путь может быть получен из двух подпутей, а свойство нового пути зависит только от свойств исходных подпутей. - -Таким образом, дополнительная операция, обозначим её $\otimes: S \times S \to S$\footnote{При первом рассмотрении такой выбор кажется контринтуитивным. Действительно, ведь при соединении путей мы как бы ``складываем'' их веса. Но при более детальном анализе поведения этой операции, в частности, относительно нейтрального элемента, становится понятно, что она ведёт себя очень похоже на умножение. Вероятно, стоит обратить внимание на операцию конкатенации, которая, с одной стороны, ``делает то, что нам нужно'', а с другой, (и неспроста) часто обозначается $\cdot$.}, должна вести себя следующим образом. Пусть $S$ --- носитель моноида, $\mathbb{0} \in S$ --- нейтральный элемент относительно $\oplus$. -\begin{itemize}\label{itm:otimesIntro} - \item $s_1 \otimes s_2 = s_3, s_i \in S, s_i \neq \mathbb{0}$ : если существует путь $i \pi j$ со свойством $s_1$ и путь $j \pi k$ со свойством $s_2$, то существует путь $i \pi k$ со свойством $s_3$. - \item $s \otimes \mathbb{0} = \mathbb{0}$ : если существует путь $i \pi j$ со свойством $s$ и не существует пути $j \pi k$, то не существует и пути $i \pi k$. - \item $\mathbb{0} \otimes s = \mathbb{0}$ : если не существует пути $i \pi j$ и существует путь $j \pi k$ со свойством $s$, то не существует и пути $i \pi k$. - \item $\mathbb{0} \otimes \mathbb{0} = \mathbb{0}$ : если не существует пути $i \pi j$ и не существует пути $j \pi k$, то не существует и пути $i \pi k$. -\end{itemize} - -Новую операцию добавим к моноиду и получим новую алгебраическую структуру $\mathbb{G}' = (S, \oplus,\otimes)$. Данная структура является коммутативным моноидом по сложению (по построению) с нейтральным элементом $\mathbb{0}$. Из построения $\otimes$ видно, что $\mathbb{0}$ является аннигилятором. Ничего более про операцию $\otimes$, а значит и про $\mathbb{G}'$ мы сказать, исходя из построения, не можем. Классический фреймворк для решения algebraic path problem подразумевает, что $\mathbb{G}'$ является полукольцом, однако далее мы увидим, что существуют задачи, в которых $\otimes$, например, не является ассоциативной\footnote{Такой будет рассматриваемая в данной работе задача достижимости с ограничениями в терминах формальных языков. Другие примеры можно найти в уже упоминавшейся работе~\cite{Baras2010PathPI}.}. А значит, согласно нашему определению, $\mathbb{G}'$ полукольцом не является. - -Теперь, когда построена алгебраическая структура, обеспечивающая вычисление формулы~ -\ref{eq:algPathProblem}, мы можем предложить алгоритм вычисления этой формулы и данным алгоритмом в интересующих нас частных случаях будет являться алгоритм Флойда-Уоршелла~\cite{Floyd1962, Bernard1959, Warshall1962}. Псевдокод алгоритма представлен на листинге~\ref{lst:algoFloydWarxhall}, а его сложность $O(n^3)$. Он практически дословно основан на описанной выше идее сборки путей из двух подпутей: тройной вложенный цикл перебирает все возможные разбиения пути на две части, а в строке 7 как раз и происходит вычисление формулы~ -\ref{eq:algPathProblem}. - -Необходимо обратить внимание на несколько вещей. Первая --- порядок обхода. Внешний цикл перебирает возможные точки разбиения (хотя мог бы, например, перебирать начальные вершины) для того, чтобы гарантировать правильный порядок вычисления подпутей (информация ни о каких подпутях не будет получена после того, как они поучаствовали в построении более длинного пути). Вторая --- количество итераций. В данном случае мы ограничились тройным вложенным циклом от 0 до $n$ и для наших задач этого будет достаточно, однако, как доказательство этого факта, так и построение аналогичного алгоритма для других задач требует аккуратного анализа решаемой задачи и последующего доказательства корректности построенного алгоритма. - -\begin{algorithm} - \floatname{algorithm}{Listing} -\begin{algorithmic}[1] -\caption{Алгоритм Флойда-Уоршелла} -\label{lst:algoFloydWarxhall} -\Function{FloydWarshall}{$\mathcal{G}$} - \State{$M \gets$ матрица смежности $\mathcal{G}$} - \Comment{Матрица над $\mathbb{G}=(S,\oplus,\otimes)$} - \State{$n \gets |V(\mathcal{G})|$} - \For{k = 0; k < n; k++} - \For{i = 0; i < n; i++} - \For{j = 0; j < n; j++} - \State{$M[i,j] \gets M[i,j] \oplus (M[i,k] \otimes M[k,j])$} - \EndFor - \EndFor - \EndFor -\State \Return $M$ -\EndFunction -\end{algorithmic} -\end{algorithm} - -Хотя изначально данный алгоритм был предложен для решения задачи о кратчайших путях, при абстрагировании алгебраической структуры он превращается в алгоритм решения целого ряда задач. В частности --- нахождения транзитивного замыкания. Так, если возьмём тропическое полукольцо $(\mathbb{R}_{+\infty}, \min, +)$, то получим алгоритм для поиска кратчайших путей. Если же возьмём булево полукольцо, то получим алгоритм для построения транзитивного замыкания графа. - -\begin{example}[Транзитивное замыкание графа]\label{exmpl:transitiveClosure} - Пусть дан следующий граф: - \begin{center} - \input{figures/graph/graph2.tex} - \end{center} - - Его матрица смежности: - $$ M = - \begin{pmatrix} - 0 & 1 & 0 & 0 \\ - 0 & 0 & 1 & 0 \\ - 1 & 0 & 0 & 1 \\ - 0 & 0 & 1 & 0 - \end{pmatrix} - $$ - - Здесь мы считаем, что отношение достижимости не рефлексивно: все диагональные элементы матрицы $M$ равны 0. - - Воспользовавшись алгоритмом из листинга~\ref{lst:algoFloydWarxhall}, специализированного на случай булева полукольца, можно получить следующую матрицу смежности. - - $$ M' = - \begin{pmatrix} - 1 & 1 & 1 & 1 \\ - 1 & 1 & 1 & 1 \\ - 1 & 1 & 1 & 1 \\ - 1 & 1 & 1 & 1 - \end{pmatrix} - $$ - - А значит, транзитивным замыканием исходного графа является полный граф и он выглядит следующим образом. - - \begin{center} - \input{figures/graph/graph5.tex} - \end{center} - -\end{example} - -Заметим, что рефлексивность отношения (значения элементов на главной диагонали матрицы смежности) непосредственно связана с особенностями решаемой задачи. Например, если говорить о кратчайших расстояниях, то кажется естественным считать расстояние от вершины до самой себя равной нулю. Однако для задачи транзитивного замыкания это уже не столь естественное предположение и часто отдельно говорят о рефлексивно-транзитивном замыкании, которое отдельно явным образом привносит рефлексивность (петли, диагональные элементы матрицы смежности). - -Аналогичным образом, используя данный алгоритм, но уже для тропического полукольца, можно решить задачу о поиске кратчайших путей для графа из примера~\ref{example:apspGraph}. - -Идеи, заложенные в алгоритме Флойда-Уоршелла, а также возможность абстрагировать его, помогут нам в дальнейшем предложить алгоритм для задачи достижимости с ограничениями в терминах формальных языков. - - -\section{Анализ путей в графе и линейная алгебра} - -В данной главе мы рассмотрим некоторые связи\footnote{Связь между графами и линейной алгеброй --- обширная область, в которой можно даже выделить отдельные направления, такие как спектральная теория графов. С точки зрения практики данная связь также подмечена давно и более полно с ней можно ознакомиться, например, в работах~\cite{doi:10.1137/1.9780898719918, Davis2018Algorithm9S}. Кроме этого, много полезной информации можно найти на сайте \url{https://graphblas.github.io/GraphBLAS-Pointers/}.} между графами и операциями над ними и матрицами и операциями над матрицами. - -Как мы видели, достаточно естественное представление графа --- это его матрица смежности. Далее можно заметить некоторое сходство между определением матричного умножения~\ref{def:MxM} и мыслями, которыми мы руководствовались, вводя операцию $\otimes$ (\ref{itm:otimesIntro}). -Действительно, пусть есть матрица $M$ размера $n \times n$ над $\mathbb{G} = (S,\oplus,\otimes)$\footnote{Здесь мы уже сталкиваемся с тем, что могут иметь смысл относительно экзотические алгебраические структуры. Действительно, как мы выяснили, матрица смежности может быть определена на чем-то более бедным, чем полукольцо, а матичное умножение мы определяли над полукольцом. Но если задуматься, то и для определения произведения матриц полукольцо вовсе необязательно, достаточно более бедной структуры.} --- матрица смежности графа. Умножим её саму на себя: вычислим $M'= M \cdot M$. Тогда, по~\ref{def:MxM}, $M'[i,j] = \bigoplus_{0 \leq l < n} M[i,l] \otimes M[l,j]$. Размер $M'$ также $n \times n$. То есть $M'$ задаёт такой граф, что в нём будет путь со свойством, являющимся агрегацией свойств всех путей, составленных из двух подпутей в исходном графе. А именно, если в исходном графе есть путь из $i$ в $l$ с некоторым свойством (его значение хранится в $M[i,l]$), и был путь из $l$ в $j$ (его значение хранится в $M[l,j]$), то в новом графе свойство $M[i,l] \otimes M[l,j]$ аддитивно (используя $\oplus$) учтётся в свойстве пути из $i$ в $j$. - -Таким образом, произведение матриц смежности соответствует обработке информации о путях интересующим нас образом. Это наблюдение позволяет предложить решение задач анализа свойств путей, основанное на операциях над матрицами. Рассмотрим такое решение для задачи о кратчайших путях. - -Пусть $D_k$ --- матрица кратчайших путей, состоящих не более чем из $k$ рёбер. То есть $D_k[i,j]$ --- это длина кратчайшего пути из вершины $i$ в вершину $j$, такого, что он состоит не более чем из $k$ ребер. Если такого пути нет, то $D_k[i,j] = \infty$. - -Таким образом, $D_1 = M$, где $M$ --- это матрица смежности исходного графа, а решением APSP является $D_{n-1}$, вычисляемая с помощью следующего рекуррентного соотношения: - -\begin{center} - $D(1) = M$ \\ - $D(2) = D(1) \cdot M = M^2$ \\ - $D(3) = D(2) \cdot M = M^3$ \\ - $\dots$ \\ - $D(n-1) = D(n-2) \cdot M = M^{(n - 1)}$ \\ -\end{center} - -Здесь мы пользуемся той особенностью задачи, что кратчайший путь в ориентированном графе (без отрицательных циклов) не может быть длиннее $n$\footnote{Раз отрицательных циклов нету, то проходить через одну вершину, коих $n$, больше одного раза бессмысленно.}. -Более того, мы пользуемся тем, что используемая структура именно полукольцо, а исходное отношение рефлексивно\footnote{Тот факт, что в любой вершине есть петля с весом 0, а 0 --- нейтральный для $\otimes$, позволяет не суммировать матрицы. Итоговая матрица содержит данные о путях длины \textit{не больше чем} вычисляемая степень, хотя должна бы содержать данные о путях ровно и только такой длины. Предлагается самостоятельно исследовать данный феномен.}. - -Таким образом, решение APSP сведено к произведению матриц над тропическим полукольцом, однако вычислительная сложность решения слишком большая: $O(n K(n))$, где $K(n)$ --- сложность алгоритма умножения матриц. - -Чтобы улучшить сложность, заметим, что, например, $D_3$ вычислять не обязательно, так как можно сразу вычислить $D_4$ как $D_2 \cdot D_2$. - -В итоге получим следующую последовательность вычислений: - -\begin{center} - $D_1 = M$ \\ - $D_2 = M^2 = M \cdot M$ \\ - $D_4 = M^4 = M^2 \cdot M^2$ \\ - $D_8 = M^8 = M^4 \cdot M^4$ \\ - $\dots$ \\ - $D_{2^{\log(n-1)}} = M^{2^{\log(n-1)}} = M^{2^{\log(n-1)} - 1} \cdot M^{2^{\log(n-1)} - 1}$ \\ - $D_{n-1} = D_{2^{\log(n-1)}}$ \\ -\end{center} - -Теперь вместо $n$ итераций нам нужно $\log{n}$, а итоговая сложность решения --- $O(\log{n} K(n))$\footnote{Заметим, что это оценка для худшего случая. На практике при использовании данного подхода можно прекращать вычисления как только при двух последовательных шагах получились одинаковые матрицы ($D_i = D_{i-1}$). Это приводит нас к понятию \textit{неподвижной точки}, обсуждение которого лежит за рамками повествования.}. -Данный алгоритм называется \textit{repeated squaring}\footnote{Пример решения APSP с помощью repeated squaring: \url{http://users.cecs.anu.edu.au/~Alistair.Rendell/Teaching/apac_comp3600/module4/all_pairs_shortest_paths.xhtml}}. Здесь мы предполагаем, что $n-1 = 2^k$ для какого-то $k$. На практике такое верно далеко не всегда. Если это условие не выполняется, то необходимо взять ближайшую сверху степень двойки\footnote{Кажется, что это приведёт к избыточным вычислениям. Попробуйте оценить, на сколько много лишних вычислений будет сделано в худшем случае.}. - -Таким образом, APSP сводится к умножению матриц над полукольцом, что, к сожалению, не позволяет этим путём получить истинно субкубический алгоритм для задачи. тем не менее, позволяет получить слегка субкубический. Приведем некоторые работы по APSP для ориентированных графов с вещественными весами (здесь $n$ --- количество вершин в графе), по которым можно более детально ознакомиться как с историей вопроса, так и с текущими результатами: -\begin{itemize} - \item M.L. Fredman (1976) --- $O(n^3(\log \log n / \log n)^\frac{1}{3})$ --- использование дерева решений~\cite{FredmanAPSP1976} - \item W. Dobosiewicz (1990) --- $O(n^3 / \sqrt{\log n})$ --- использование операций на Word Random Access Machine~\cite{Dobosiewicz1990} - \item T. Takaoka (1992) --- $O(n^3 \sqrt{\log \log n / \log n})$ --- использование таблицы поиска~\cite{Takaoka1992} - \item Y. Han (2004) --- $O(n^3 (\log \log n / \log n)^\frac{5}{7})$~\cite{Han2004} - \item T. Takoaka (2004) --- $O(n^3 (\log \log n)^2 / \log n)$~\cite{Takaoka2004} - \item T. Takoaka (2005) --- $O(n^3 \log \log n / \log n)$~\cite{Takaoka2005} - \item U. Zwick (2004) --- $O(n^3 \sqrt{\log \log n} / \log n)$~\cite{Zwick2004} - \item T.M. Chan (2006) --- $O(n^3 / \log n)$ --- многомерный принцип ``разделяй и властвуй''~\cite{Chan2008} -\end{itemize} - -Вопрос же о истинно субкубических алгоритмах решения APSP всё ещё открыт~\cite{Chan2010} и активно обсуждается в научном сообществе. - -Аналогичным образом можно свести транзитивное замыкание к матричным операциям. Предлагаем проделать это самостоятельно, заодно обратив внимание на важность рефлексивности (в примере~\ref{exmpl:transitiveClosure} её нет). - -Заметим, что оптимизация, связанная с возведением в квадрат возможна только при ассоциативности произведения матриц, что зависит от свойств алгебраической структуры, над которой построены матрицы. Для полукольца такая оптимизация законна, однако в некоторых случаях её применить нельзя. Таким случаем как раз и будет рассматриваемая в нашей работе задача. Поэтому построение алгоритма её решения через операции над матрицами, хотя и будет основано на указанных выше соображениях, но будет сопряжено с некоторыми трудностями. - - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item Реализуйте абстракцию полукольца, позволяющую конструировать полукольца с произвольными операциями. -% \item Реализуйте алгоритм произведения матриц над произвольным полукольцом. Используйте результат решения предыдущей задачи. -% \item Используя результаты предыдущих задач, реализуйте алгоритм построения транзитивного замыкания через произведение матриц. -% \item Используя результаты предыдущих задач, реализуйте алгоритм решения задачи APSP для ориентированного через произведение матриц. -% \item Используя существующую библиотеку линейной алгебры для CPU, решите задачу построения транзитивного замыкания графа. -% \item Используя существующую библиотеку линейной алгебры для CPU, решите задачу APSP для ориентированного графа. -% \item Используя существующую библиотеку линейной алгебры для GPGPU, решите задачу построения транзитивного замыкания графа. -% \item Используя существующую библиотеку линейной алгебры для GPGPU, решите задачу APSP для ориентированного графа. -% \item Сравните произволительность решений предыдущих задач -%\end{enumerate} diff --git a/tex/Introduction.tex b/tex/Introduction.tex deleted file mode 100644 index 2c8c9e5..0000000 --- a/tex/Introduction.tex +++ /dev/null @@ -1,78 +0,0 @@ -\chapter*{Введение\markboth{Введение}{}} - -Теория формальных языков находит применение не только в ставших уже классическими задачах синтаксического анализа кода (языков программирования, искусственных языков) и естественных языков, но и в других областях, таких как статический анализ кода, графовые базы данных, биоинформатика, машинное обучение. - -Например, в машинном обучении использование формальных грамматик позволяет передать искусственной генеративной нейронной сети, предназначенной для построения цепочек с определёнными свойствами, знания о синтаксической структуре этих цепочек, что позволяет существенно упростить процесс обучения и повысить качество результата~\cite{10.5555/3305381.3305582}. -Вместе с этим, развиваются подходы, позволяющие нейронным сетям наоборот извлекать синтаксическую структуру (строить дерево вывода) для входных цепочек~\cite{kasai-etal-2017-tag,kasai-etal-2018-end}. - -В биоинформатике формальные грамматики нашли широкое применение для описания особенностей вторичной структуры геномных и белковых последовательностей~\cite{Dyrka2019,WJAnderson2012,zier2013rna}. -Соответствующие алгоритмы синтаксического анализа используются при создании инструментов обработки данных. - -Таким образом, теория формальных языков выступает в качестве основы для многих прикладных областей, а алгоритмы синтаксического анализа применимы не только для обработки естественных языков или языков программирования. -Нас же в данной работе будет интересовать применение теории формальных языков и алгоритмов синтаксического анализа для анализа графовых баз данных и для статического анализа кода. - -Одна из классических задач, связанных с анализом графов --- это поиск путей в графе. -Возможны различные формулировки этой задачи. -В некоторых случаях необходимо выяснить, существует ли путь с определёнными свойствами между двумя выбранными вершинами. -В других же ситуациях необходимо найти все пути в графе, удовлетворяющие некоторым свойствам или ограничениям. -Например, в качестве ограничений можно указать, что искомый путь должен быть простым, кратчайшим, гамильтоновым и так далее. - -Один из способов задавать ограничения на пути в графе основан на использовании формальных языков. -Базовое определение языка говорит нам, что язык --- это множество слов над некоторым алфавитом. -Если рассмотреть граф, рёбра которого помечены символами из алфавита, то путь в таком графе будет задавать слово: достаточно соединить последовательно символы, лежащие на рёбрах пути. -Множество же таких путей будет задавать множество слов или язык. -Таким образом, если мы хотим найти некоторое множество путей в графе, то в качестве ограничения можно описать язык, который должно задавать это множество. -Иными словами, задача поиска путей может быть сформулирована следующим образом: необходимо найти такие пути в графе, что слова, получаемые конкатенацией меток их рёбер, принадлежат заданному языку. -Такой класс задач будем называть задачами поиска путей с ограничениям в терминах формальных языков. - -Подобный класс задач часто возникает в областях, связанных с анализом граф-структурированных данных и активно исследуется~\cite{doi:10.1137/S0097539798337716,axelsson2011formal,10.1007/978-3-642-22321-1_24,Ward:2010:CRL:1710158.1710234,barrett2007label,doi:10.1137/S0097539798337716}. -Исследуются как классы языков, применяемых для задания ограничений, так и различные постановки задачи. - -Граф-структурированные данные встречаются не только в графовых базах данных, но и при статическом анализе кода: по программе можно построить различные графы отображающие её свойства. -Скажем, граф вызовов, граф потока данных и так далее. -Оказывается, что поиск путей в специального вида графах с использованием ограничений в терминах формальных языков позволяет исследовать некоторые нетривиальные свойства программы. -Например проводить межпроцедурный анализ указателей или анализ псевдонимов (алиасов)~\cite{Zheng,10.1145/2001420.2001440,10.1145/2714064.2660213}, строить срезы программ~\cite{10.1145/193173.195287}, проводить анализ типов~\cite{10.1145/373243.360208}. - -В данной работе представлен ряд алгоритмов для поиска путей с ограничениями в терминах формальных языков. -Основной акцент будет сделан на контекстно-свободных языках, однако будут затронуты и другие классы: регулярные, многокомпонентные контекстно-свободные (Multiple Context-Free Languages, MCFL~\cite{SEKI1991191}) и конъюнктивные языки. -Будет показано, что теория формальных языков и алгоритмы синтаксического анализа применимы не только для анализа языков программирования или естественных языков, а также для анализа графовых баз данных и статического анализа кода, что приводит к возникновению новых задач и переосмыслению старых. - - -Структура данной работы такова. -В начале (в части~\ref{chpt:GraphTheoryIntro}) мы рассмотрим основные понятия из теории графов, необходимые в данной работе. Данные разделы являются подготовительными и не обязательны к прочтению, если такие понятия как \textit{ориентированный граф} и \textit{матрица смежности} уже известны читателю. Более того, они лишь вводят определения, подразумевая, что более детальное изучение соответствующих разделов науки остается за рамками этой работы и скорее всего уже проделано читателем. -Затем, в главе~\ref{chpt:FormalLanguageTheoryIntro} мы введём основные понятия из теории формальных языков. -Далее, в главе~\ref{chpt:FLPQ} рассмотрим различные варианты постановки задачи поиска путей с ограничениями в терминах формальных языков, обсудим базовые свойства задач, её разрешимость в различных постановках и т.д.. -И в итоге зафиксируем постановку, которую будем изучать далее. -После этого, в главах~\ref{chpt:CFPQ_CYK}--\ref{chpt:GLR} мы будем подробно рассматривать различные алгоритмы решения этой задачи, попутно вводя специфичные для рассматриваемого алгоритма структуры данных. -Большинство алгоритмов будут основаны на классических алгоритмах синтаксического анализа, таких как CYK или LR. -%Все главы, начиная с~\ref{chpt:GraphTheoryIntro}, снабжены списком вопросов и задач для самостоятельного решения и закрепления материала. - -\begin{center} - \begin{tikzpicture}[shorten >=1pt,on grid,auto] - \node (q_linal) [text width=4cm] {Некоторые понятия линейной алгебры}; - \node (q_graphtheory) [below of=q_linal, text width=4cm] {Некоторые сведения из теории графов}; - \node (q_fortmallang) [right of=q_graphtheory, text width=4cm] {Общие сведения теории формальных языков}; - \node (q_reglang) [below of=q_fortmallang, text width=4cm] {Регулярные языки}; - \node (q_cflang) [right of=q_reglang, text width=4cm] {Контекстно-свободные языки и грамматики}; - \node (q_mcfl) [right of=q_cflang, text width=4cm] {Многокомпонентные контекстно-свободные языки}; - \node (q_flpq) [below of=q_graphtheory, text width=4cm] {Пути с ограничениями в терминах формальных языков}; - - \node (q_rpq) [below of=q_reglang, text width=4cm] {Поиск путей с регулярными ограничениями}; - \node (q_cfpq) [below of=q_cflang, text width=4cm] {Пути с ограничениями в терминах контекстно-свободных языков}; - \node (q_mcfpq) [below of=q_mcfl, text width=4cm] {Пути с ограничениями в терминах многокомпонентных контекстно-свободных языков}; - \path[->] - (q_linal) edge node {} (q_graphtheory) - (q_graphtheory) edge node {} (q_flpq) - (q_fortmallang) edge node {} (q_flpq) - (q_fortmallang) edge node {} (q_reglang) - (q_fortmallang) edge node {} (q_cflang) - (q_fortmallang) edge node {} (q_mcfl) - (q_reglang) edge node {} (q_rpq) - (q_cflang) edge node {} (q_cfpq) - (q_mcfl) edge node {} (q_mcfpq) - (q_flpq) edge node {} (q_rpq) - (q_flpq) edge node {} (q_cfpq) - (q_flpq) edge node {} (q_mcfpq) - ; - \end{tikzpicture} -\end{center} \ No newline at end of file diff --git a/tex/LinearAlgebra.tex b/tex/LinearAlgebra.tex deleted file mode 100644 index 6eb03a4..0000000 --- a/tex/LinearAlgebra.tex +++ /dev/null @@ -1,774 +0,0 @@ -\chapter[Некоторые понятия линейной алгебры]{Некоторые понятия линейной алгебры\footnote{Неообходимо понимать, что, с одной строны, в данном разделе рассматриваются самые базовые понятия, которые даются практически в любом учебнике алгебры. С другой же стороны, определения данных понятий оказываются весьма вариативными и часто вызывают дискуссии. Напрмиер, интересный анализ тонкостей определения группы можно найти в первом и втором параграфах первого раздела книги Николая Александровича Вавилова ``Конкретная теория групп''~\cite{VavilovGroups}. Мы же дадим определения, удобные для дальнейшего изложения материала.}}\label{chpt:LinAlIntro} - -При изложении ряда алгоритмов будут активно использоваться некоторые понятия и инструменты линейной алгебры, такие как моноид, полукольцо или матрица. -В данном разделе необходимые понятия будут определены и приведены некоторые примеры соответствующих конструкций. Для более глубокого изучения материала рекомендуются обратиться к соответствующим разделам алгебры. - - -\section{Бинарные операции и их свойства} - - -Введём понятие \textit{бинарной операции} и рассмотрим некоторые её свойства, такие как \textit{коммутативность} и \textit{ассоциативность}. - -\begin{definition} - \textit{Функцией} будем называть бинарное отношение на двух множествах $X$ и $Y$, такое, что каждому элементу из $X$ сопоставляется ровно один элемент из $Y$. Запись $f: X \to Y$ как раз и обозначает, что функция $f$ сопоставляет элементы из $X$ элементам из $Y$. -\end{definition} - -\begin{definition} - Для функции $f: X \to Y$, множество $X$ называется \textit{областью определения функции} или \textit{доменом функции}. -\end{definition} - -\begin{definition} - Для функции $f: X \to Y$, множество $Y$ называется \textit{областью значений функции} или \textit{кодоменом функции}. -\end{definition} - -\begin{definition} - Функцию, принимающую два аргумента, $f: S \times K \to Q$ будем называть \emph{двухместной} или \emph{функцией арности два}. -Для записи таких функций будем использовать типичную нотацию: $c = f(a,b)$. -\end{definition} - - -\begin{definition} -\emph{Бинарная операция} --- это двухместная функция, от которой дополнительно требуется, чтобы оба аргумента и результат лежали в одном и том же множестве: $f: S \times S \to S$. В таком случае говорят, что бинарная операция определена на некотором множестве $S$. Для обозначения произвольной бинарной операции будем использовать символ $\circ$ и пользоваться инфиксной нотацией для записи: $c = a \circ b$. -\end{definition} - - - - -\begin{definition} -\emph{Внешняя бинарная операция} --- это бинарная операция, у которой аргументы лежат в разных множествах, при этом результат --- в одном из этих множеств. Иными словами $\circ: K \times S \to S$, где $K$ может не совпадать с $S$ --- внешняя бинарная операция. -\end{definition} - - -Необходимо помнить, что как функции, так и бинарные операции, могут быть частично определёнными (частичные функции, частичные бинарные операции). Типичным примером частично определённой бинарной операции является деление на целых числах: она не определена, если второй аргумент равен нулю. - - -Бинарные операции могут обладать некоторыми дополнительными свойствами, такими как \textit{коммутативность} или \textit{ассоциативность}, позволяющими преобразовывать выражения, составленные с использованием этих операций. - - -\begin{definition} -Бинарная операция $\circ : S \times S \to S$ называется \emph{коммутативной}, если для любых $x_1 \in S, x_2 \in S$ верно, что $x_1 \circ x_2 = x_2 \circ x_1$. -\end{definition} - -\begin{example} Рассмотрим несколько примеров коммутативных и некоммутативных операций. - \begin{itemize} - \item Операция сложения на целых числах $+$ является коммутативной: известный ещё со школы перестановочный закон сложения. - \item Операция конкатенации на строках $\cdot$ не является коммутативной: $$``ab" \cdot ``c" \, = ``abc" \neq ``cab" \, = ``c" \cdot ``ab".$$ - \item Операция умножения на целых числах является коммутативной: известный ещё со школы перестановочный закон умножения. - \item Операция умножения матриц (над целыми числами) $\cdot$ не является коммутативной: - $$\begin{pmatrix} - 1 & 1 \\ 0 & 0 - \end{pmatrix} - \cdot - \begin{pmatrix} - 0 & 0 \\ 1 & 1 - \end{pmatrix} - = - \begin{pmatrix} - 1 & 1 \\ 0 & 0 - \end{pmatrix} - \neq - \begin{pmatrix} - 0 & 0 \\ 1 & 1 - \end{pmatrix} - = - \begin{pmatrix} - 0 & 0 \\ 1 & 1 - \end{pmatrix} - \cdot - \begin{pmatrix} - 1 & 1 \\ 0 & 0 - \end{pmatrix} - .$$ - \end{itemize} -\end{example} - -\begin{definition} -Бинарная операция $\circ : S \times S \to S$ называется \emph{ассоциативной}, если для любых $x_1 \in S, x_2 \in S, x_3 \in S$ верно, что $(x_1 \circ x_2) \circ x_3 = x_1 \circ (x_2 \circ x_3)$. Иными словами, для ассоциативной операции результат вычислений не зависит от порядка применения операций. -\end{definition} - -\begin{example} Рассмотрим несколько примеров ассоциативных и неассоциативных операций. - \begin{itemize} - \item Операция сложения на целых числах $+$ является ассоциативной. - \item Операция умножения на целых числах является ассоциативной. - \item Операция конкатенации на строках $\cdot$ является ассоциативной: $$(``a" \cdot ``b") \cdot ``c" \, = ``a" \cdot (``b" \cdot ``c") = ``abc" .$$ - \item Операция возведения в степень (над целыми числами) $\hat{\mkern6mu}$ не является ассоциативной: - $$(2\hat{\mkern6mu}2)\hat{\mkern6mu}3 = 4 \hat{\mkern6mu} 3 = 64 \neq 256 = 2 \hat{\mkern6mu} 8 = 2\hat{\mkern6mu}(2\hat{\mkern6mu}3).$$ - \end{itemize} -\end{example} - - -\begin{definition} -Говорят, что бинарная операция $\otimes : S \times S \to S$ является \emph{дистрибутивной} относительно бинарной операции $\oplus : S \times S \to S$, если -\begin{enumerate} - \item Для любых $x_1,x_2,x_3 \in S, x_1 \otimes (x_2 \oplus x_3) = (x_1 \otimes x_2) \oplus (x_1 \otimes x_3)$ (дистрибутивность слева). - \item Для любых $x_1,x_2,x_3 \in S, (x_2 \oplus x_3) \otimes x_1 = (x_2 \otimes x_1) \oplus (x_3 \otimes x_1)$ (дистрибутивность справа). -\end{enumerate} - -Если операция $\otimes$ является коммутативной, то дистрибутивность слева и справа равносильны. - -\end{definition} - -\begin{example} Рассмотрим несколько примеров дистрибутивных операций. - -\begin{itemize} - \item Умножение целых чисел дистрибутивно относительно сложения и вычитания: классический \textit{распределительный закон}, знакомый всем со школы. - \item Операция деления (допустим, на действительных числах) не коммутативна. При этом, она дистрибутивна справа относительно сложения и вычитания, но не дистрибутивна слева\footnote{Здесь может быть уместно вспомнить правила сложения дробей. Дроби с общим знаминателем складывать проще как раз из-за дистрибутивности справа.}. - $$(a + b) / c = (a / c) + (b / c) $$ - но - $$c / (a + b) \neq (c / a) + (c / b).$$ -\end{itemize} - -\end{example} - -\begin{definition} -Бинарная операция $\circ : S \times S \to S$ называется \emph{идемпотентной}, если для любого $x \in S$ верно, что $x \circ x = x$. -\end{definition} - - - -\begin{example} Рассмотрим несколько примеров идемпотентных операций. - -\begin{itemize} - \item Операция объединения множеств $\cup$ является идемпотентной: для любого множества $S$ верно, что $S \cup S = S$. - \item Операция сложения на целых числах не является идемпотентной. - \item Операции ``логическое и'' $\wedge$ и ``логическое или'' $\vee$ являются идемпотентными. - \item Операция ``исключающее или'' (\texttt{XOR}) не является идемпотентной. -\end{itemize} - -\end{example} - -\begin{definition} -Пусть есть коммутативная бинарная операция $\circ$ на множестве $S$. Говорят, что $x\in S$ является \emph{нейтральным элементом} по операции $\circ$, если для любого $y\in S$ верно, что $x \circ y = y \circ x = y$. Если бинарная операция не является коммутативной, то можно определить \textit{нейтральный слева} и \textit{нейтральный справа} элементы по аналогии. -\end{definition} - - -\section{Полугруппа} - - -\begin{definition} -Множество $S$ с заданной на нём ассоциативной бинарной операцией $\cdot : S \times S \to S$ называется \emph{полугруппой} и обозначается $(S, \cdot)$. -Если операция $\cdot$ является коммутативной, то говорят о \textit{коммутативной полугруппе}. -\end{definition} - - -\begin{example} Приведём несколько примеров полугрупп. -\begin{itemize} - \item Множество положительных целых чисел с операцией сложения является коммутативной полугруппой. - \item Множество целых чисел с операцией взятия наибольшего из двух ($\max$) является коммутативной полугруппой. - \item Множество всех строк конечной длины без пустой строки\footnote{Множество всех строк конечной длины c пустой строкой также является полугруппой. Однако, такая структура является ещё и моноидом, что будет показано далее.} над фиксированным алфавитом $\Sigma$ с операцией конкатенации является полугруппой. Так как конкатенация на строках не является коммутативной операцией, то и полугруппа не является коммутативной. -\end{itemize} -\end{example} - - -\section{Моноид} - - -\begin{definition} - \emph{Моноидом} называется полугруппа с нейтральным элементом. Если операция является коммутативной, то можно говорить о \emph{коммутативном моноиде}. -\end{definition} - -\begin{example} Приведём примеры моноидов, построенных на основе полугрупп из предыдущего раздела. - -\begin{itemize} - \item Неотрицательные целые числа (или же натуральные числа с нулём) с операцией сложения являются моноидом. Нейтральный элемент --- $0$. - \item Целые числа, дополненные значением $-\infty$ (``минус-бесконечность'') с операцией взятия наибольшего из двух ($\max$) являются моноидом. Нейтральный элемент --- $-\infty$. - \item Множество всех строк конечной длины с пустой строкой (строка длины 0) над фиксированным алфавитом $\Sigma$ и операцией конкатенации является моноидом. Нейтральный элемент --- пустая строка. - \item Квадратные неотрицательные матрицы\footnote{Неотрицательной называется матрица, все элементы которой не меньше нуля.} фиксированного размера с операцией умножения задают моноид. Нейтральный элемент --- единичная матрица. -\end{itemize} -\end{example} - - -\section{Группа} - -\begin{definition} -Непустое\footnote{Требование непустоты здесь, как и далее, в определениях полукольца и кольца --- дискуссионный вопрос.} множество $G$ с заданной на нём бинарной операцией $\circ: {G} \times {G} \to {G}$ называется \emph{группой} $(G ,\circ)$, если выполнены следующие аксиомы: -\begin{enumerate} -\item ассоциативность: $\forall (a,b,c\in G)\colon (a\circ b)\circ c = a\circ (b \circ c)$; -\item наличие нейтрального элемента: $ \exists e \in G \quad \forall a\in G\colon (e \circ a = a \circ e = a)$; -\item наличие обратного элемента: $ \forall a\in G\quad \exists a^{-1}\in G\colon (a \circ a^{-1}=a^{-1} \circ a = e)$. -\end{enumerate} - -Иными словами, группа --- это моноид с дополнительным требованием наличия обратных элементов. -\end{definition} - -\begin{definition} -Если операция $\circ$ коммутативна, то говорят, что группа \textit{Абелева}. -\end{definition} - -\begin{example} -Рассмотрим несколько примеров групп. -\begin{itemize} - \item Целые числа $\mathbb{Z}$ с операцией сложения $+$ являются группой. Получается дополнением моноида из предыдущего раздела обратными по сложению элементами. - \item Целые числа $\mathbb{Z}$ без нуля\footnote{При наличии нуля возникают трудности с нейтральным элементом. Логично считать $1$ нейтральным по умножению, однако $0\cdot1 = 0$, а не 1, как того требует определение.} с операцией умножения $\cdot$ не являются группой, так как нет обратных по умножению. Действительно, возьмём $a = 3$, тогда должен существовать $a^{-1} \in \mathbb{Z}$, такой что $3 \cdot a^{-1} = 1$. Видим, что $a^{-1} = \frac{1}{3}$, но $\frac{1}{3} \notin \mathbb{Z}$. - \item Множество обратимых\footnote{Квадратная матрица $M$ называется обратимой, если существует матрица $N$, называемая обратной, такая что $M \cdot N = N \cdot M = I$, где $I$ --- единичная матрица. К сожалению, не все матрицы являются обратимыми, потому, чтобы сконструировать группу, нам приходится требовать обратимость явно.} матриц с операцией матричного умножения задают группу. -\end{itemize} -\end{example} - -\section{Полукольцо} - -\begin{definition} - -Непустое множество $R$ с двумя бинарными операциями $\oplus\colon R \times R \to R$ (часто называют сложением) и $\otimes \colon R \times R \to R$ (часто называют умножением) называется \emph{полукольцом}, если выполнены следующие условия. -\begin{enumerate} - -\item $(R, \oplus)$ --- это коммутативный моноид, нейтральный элемент которого --- $\mathbb{0}$. Для любых $a,b,c \in R$: -\begin{itemize} - \item $(a \oplus b) \oplus c = a \oplus (b \oplus c)$ - \item $\mathbb{0} \oplus a = a \oplus \mathbb{0} = a$ - \item $a \oplus b = b \oplus a$ -\end{itemize} - -\item $(R, \otimes)$ --- это моноид, нейтральный элемент которого --- $\mathbb{1}$. Для любых $a,b,c \in R$: -\begin{itemize} - \item $(a \otimes b) \otimes c = a \otimes (b \otimes c)$ - \item $\mathbb{1} \otimes a = a \otimes \mathbb{1} = a$ -\end{itemize} - -\item $\otimes$ дистрибутивно слева и справа относительно $\oplus$: -\begin{itemize} - \item $a \otimes (b \oplus c) = (a \otimes b) \oplus (a \otimes c)$ - \item $(a \oplus b) \otimes c = (a \otimes c) \oplus (b \otimes c)$ -\end{itemize} - - -\item $\mathbb{0}$ является \textit{аннигилятором} по умножению: -\begin{itemize} - \item $\forall a \in R: \mathbb{0} \otimes a = a \otimes \mathbb{0} = \mathbb{0}$ -\end{itemize} - -\end{enumerate} - -Если операция $\otimes$ коммутативна, то говорят о коммутативном полукольце. -Если операция $\oplus$ идемпотентна, то говорят об идемпотентном полукольце. - -\end{definition} - -\begin{example}\label{exmpl:semiring} -Рассмотрим пример полукольца, а заодно покажем, что левая и правая дистрибутивность могут существовать независимо для некоммутативного умножения\footnote{Хороший пример того, почему левую и правую дистрибутивность в случае некоммутативного умножения нужно проверять независимо (правда, для колец), приведён Николаем Александровичем Вавиловым в книге ``Конкретная теория колец'' на странице 6~\cite{VavilovRings}.}. - -В качестве $R$ возьмём множество множеств строк конечной длины над некоторым алфавитом $\Sigma$. В качестве сложения возьмём теоретико-множественное объединение: $\oplus \equiv \cup$. Нейтральный элемент по сложению --- это пустое множество ($\varnothing$). -В качестве умножения возьмём конкатенацию множеств ($\otimes \equiv \odot$) и определим её следующим образом: -$$ S_1 \odot S_2 = \{ w_1 \cdot w_2 \mid w_1 \in S_1, w_2 \in S_2\}$$, где $\cdot$ --- конкатенация строк. Нейтральным элементом по умножению будет являться множество из пустой строки: $\{\varepsilon\}$, где $\varepsilon$ --- обозначение для пустой строки. - -Проверим, что $(R, \cup, \odot)$ действительно полукольцо по нашему определению. - -\begin{enumerate} - -\item $(R, \cup)$ --- действительно коммутативный моноид с нейтральным элементом $\varnothing$. Для любых $a,b,c \in R$ по свойствам теоретико-множественного объединения верно: -\begin{itemize} - \item $(a \cup b) \cup c = a \cup (b \cup c)$ - \item $\varnothing \cup a = a \cup \varnothing = a$ - \item $a \cup b = b \cup a$. -\end{itemize} - -\item $(R, \odot)$ --- действительно моноид с нейтральным элементом $\{\varepsilon\}$. Для любых $a,b,c \in R$: -\begin{itemize} - \item $(a \odot b) \odot c = a \odot (b \odot c)$ по определению $\odot$ - \item $\{\varepsilon\} \odot a = \{\varepsilon \cdot w \mid w \in a \} = \{w \mid w \in a \} = a \odot \{\varepsilon\} = a$ -\end{itemize} -Вообще говоря, сконструированный нами моноид не является коммутативным: легко проверить, например, что существуют непустые $a,b \in R, a \neq b, a \neq \{\varepsilon\}, b \neq \{\varepsilon\}$: $a \cdot b \neq b \cdot a$ по причине некоммутативности конкатенации строк. - -\item $\odot$ дистрибутивно слева и справа относительно $\cup$: -\begin{itemize} - \item Сначала проверим дистрибутивность слева. - \begin{align*} - a \odot (b \cup c) & = \{ w_1 \cdot w_2 \mid w_1 \in a, w_2 \in b \cup c\} \\ - & = \{ w_1 \cdot w_2 \mid w_1 \in a, w_2 \in b \} \cup \{ w_1 \cdot w_2 \mid w_1 \in a, w_2 \in c \} \\ - & = (a \odot b) \cup (a \odot c) - \end{align*} - - \item Аналогично, $(a \cup b) \odot c = (a \odot c) \cup (b \odot c)$ -\end{itemize} -При этом, в общем случае, $a \odot (b \cup c) \neq (b \cup c) \odot a$ из-за некоммутативности операции $\odot$. Действительно, - -\begin{align*} - & \{``a"\}\odot(\{``b"\} \cup \{``c"\}) = \{``a"\}\odot \{``b" \ ,``c" \} = \{``ab"\ ,``ac" \} \neq \\ - \neq & (\{``b"\} \cup \{``c"\}) \odot \{``a"\} = \{``b",``c" \} \odot \{``a"\} = \{``ba"\ ,``ca" \} -\end{align*} - - -\item $\varnothing$ является \textit{аннигилятором} по умножению: для любого $a \in R$ верно, что -$\varnothing \odot a = \{ w_1 \cdot w_2 \mid w_1 \in \varnothing, w_2 \in a \} = \{ w_1 \cdot w_2 \mid w_1 \in a, w_2 \in \varnothing \} = a \odot \varnothing = \varnothing$ - -\end{enumerate} - -\end{example} - -\section{Кольцо} - - -\begin{definition} - -Непустое множество $R$ с двумя бинарными операциями $\oplus\colon R \times R \to R$ (умножение) и $\otimes \colon R \times R \to R$ (сложение) называется \emph{кольцом}, если выполнены следующие условия. -\begin{enumerate} - -\item $(R, \oplus)$ --- это Абелева группа, нейтральный элемент которой --- $\mathbb{0}$. Для любых $a,b,c \in R$: -\begin{itemize} - \item $(a \oplus b) \oplus c = a \oplus (b \oplus c)$ - \item $\mathbb{0} \oplus a = a \oplus \mathbb{0} = a$ - \item $a \oplus b = b \oplus a$ - \item для любого $a \in R$ существует $-a \in R$, такое что $a + (-a) = \mathbb{0}$. -\end{itemize} -В последнем пункте кроется отличие от полукольца. - -\item $(R, \otimes)$ --- это моноид, нейтральный элемент которого --- $\mathbb{1}$. Для любых $a,b,c \in R$: -\begin{itemize} - \item $(a \otimes b) \otimes c = a \otimes (b \otimes c)$ - \item $\mathbb{1} \otimes a = a \otimes \mathbb{1} = a$ -\end{itemize} - -\item $\otimes$ дистрибутивно слева и справа относительно $\oplus$: -\begin{itemize} - \item $a \otimes (b \oplus c) = (a \otimes b) \oplus (a \otimes c)$ - \item $(a \oplus b) \otimes c = (a \otimes c) \oplus (b \otimes c)$ -\end{itemize} - -\end{enumerate} - -Заметим, что мультипликативное свойство $\mathbb{0}$ (быть аннигилятором по умножению) не указыватеся явно, так как может быть выведено из остальных утверждений. Действительно, -\begin{enumerate} - \item $a \otimes \mathbb{0} = a \otimes (\mathbb{0} \oplus \mathbb{0})$, так как $\mathbb{0}$ --- нейтральный по сложению, то $\mathbb{0} \oplus \mathbb{0} = \mathbb{0}$ - \item Воспользуемся дистрибутивностью: $a \otimes (\mathbb{0} \oplus \mathbb{0}) = a \otimes \mathbb{0} \oplus a \otimes \mathbb{0}$. В итоге: $a \otimes \mathbb{0} = a \otimes \mathbb{0} \oplus a \otimes \mathbb{0}$ - \item Так как у нас есть группа по сложению, то для любого $a$ существует обратный элемент $a^{-1}, a \oplus a^{-1} = \mathbb{0}$. Прибавим $a^{-1} \otimes \mathbb{0}$ к левой и правой части равенства\footnote{Обычно данное действие воспринимается как очевидное, но, строго говоря, оно требует аккуратного введения структур с равенством и соответствующих аксиом.}, полученного на предыдущем шаге: - $$a \otimes \mathbb{0} \oplus a^{-1} \otimes \mathbb{0} = a \otimes \mathbb{0} \oplus a \otimes \mathbb{0} \oplus a^{-1} \otimes \mathbb{0}.$$ - \item Воспользуемся дистрибутивностью и ассоциативностью. - \begin{align*} - (a \oplus a^{-1}) \otimes \mathbb{0} & = a \otimes \mathbb{0} \oplus (a \oplus a^{-1}) \otimes \mathbb{0} \\ - \mathbb{0} \otimes \mathbb{0} & = a \otimes \mathbb{0} \oplus \mathbb{0} \otimes \mathbb{0} \\ - \mathbb{0} & = a \otimes \mathbb{0} - \end{align*} - \item Аналогично можно доказать, что $\mathbb{0} = \mathbb{0} \otimes a$. -\end{enumerate} - -\end{definition} - - -%\section{Поле} - -\section{Матрицы и вектора} - -К определению матрицы мы подойдём структурно, так как в дальнейшем будем сопоставлять эту структуру с объектами различной природы, а значит определение матрицы через какой-либо из этих объектов (например через квадратичные формы) будет менее удобным. - -Договоримся, что \textit{алгебраическая структура} --- это собирательное название для объектов вида ``множество с набором операций'' (например, кольцо, моноид, группа и т.д.), а соответствующее множество будем назвать \textit{носителем} этой структуры. - -\begin{definition} - -Предположим, что у нас есть некоторая алгебраическая структура с носителем $S$. Тогда \emph{матрицей} будем называть прямоугольный массив размера $n\times m, n > 0, m > 0$, заполненный элементами из $S$. - -Говорят, что $n$ --- это высота матрицы или количество строк в ней, а $m$ --- ширина матрицы или количество столбцов. - -\end{definition} - -При доступе к элементам матрицы используются их индексы. При этом нумерация ведётся с левого верхнего угла, первым указывается строка, вторым --- столбец. В нашей работе мы будем использовать ``программистскую'' традицию и нумеровать строки и столбцы с нуля\footnote{В противоположность ``математической'' традиции нумеровать строки и столбцы с единицы. Стоит, правда, отметить, что в некоторых языках программирования (например, Fortran или COBOL) жива ``математическая'' традиция.}. - -\begin{example}[Матрица] - -Пусть есть моноид $(S,\cdot)$, где $S$ --- множество строк конечной длины над алфавитом \{a,b,c\}. -Тогда можно построить, например, следующую матрицу $2\times 3$. -$$ -M_{2\times 3} = -\begin{pmatrix} -``a" & ``ba" & ``cb" \\ -``ac" & ``bab" & ``b" \\ -\end{pmatrix} -$$ - -$$ -M_{2\times 3}[1,1] = ``bab" -$$ - -\end{example} - -К определению вектора мы также подойдём структурно. - -\begin{definition} - -\emph{Вектором} будем называть матрицу, хотя бы один из размеров которой равен единице. Если единице равна высота матрицы, то это \textit{вектор-строка}, если же единице равна ширина матрицы, то это \textit{вектор-столбец}. - -\end{definition} - - -Операции над матрицами можно условно разделить на две группы: -\begin{itemize} - \item \textit{структурные} --- не зависящие от алгебраической структуры, над которой строилась матрица, и работающие только с её структурой; - \item \textit{алгебраические} --- определение таковых опирается на свойства алгебраической структуры, над которой построена матрица. -\end{itemize} - -Примерами структурных операций является \textit{транспонирование}, \textit{взятие подматрицы} и \textit{взятие элемента по индексу}. - -\begin{definition}[Транспонирование матрицы] -Пусть дана матрица $M_{n\times m}$. Тогда результат её \emph{транспонирования}, это такая матрица $M'_{m\times n}$, что $M'[i,j] = M[j,i]$ для всех $0\leq i \leq m - 1$ и $0\leq j \leq n - 1$. - -Операцию транспонирования принято обозначать как $M^{T}$. - -\end{definition} - -\begin{example} -$$ -\begin{pmatrix} -``a" & ``ba" & ``cb" \\ -``ac" & ``bab" & ``b" \\ -\end{pmatrix}^T = -\begin{pmatrix} -``a" & ``ac" \\ -``ba" & ``bab" \\ -``cd" & ``b" \\ -\end{pmatrix} -$$ -\end{example} - - -\begin{definition}[Прямая сумма матриц] - Пусть даны матрицы $M_{n_1\times m_1}$ и $N_{n_2\times m_2}$. Тогда \emph{прямой суммой} этих матриц называется матрица $L_{n_1+n_2 \times m_1+m_2}$ вида - $$ - L = - \left[ - \begin{matrix} - M & 0 \\ - 0 & N - \end{matrix} - \right] - $$ - - Где 0 обозначает нулевой блок. Прямая сумма обозначается $L = M \bigoplus N$. - -\end{definition} - - -\begin{definition}[Взятие подматрицы] -Пусть дана матрица $M_{n\times m}$. Тогда -$ -M_{n\times m}[i_0..i_1,j_0..j_1] -$ - --- это такая $M'_{i_1 - i_0 + 1, j_1 - j_0 + 1}$ что $M'[i,j] = M[i_0 + i,j_0 + j]$ для всех $0\leq i \leq i_1 - i_0 + 1$ и $0\leq j \leq j_1 - j_0 + 1$. -\end{definition} - - -\begin{example} -$$ -\begin{pmatrix} -``a" & ``ba" & ``cb" \\ -``ac" & ``bab" & ``b" \\ -\end{pmatrix}[0..1,1..2] = -\begin{pmatrix} -``ba" & ``cb" \\ -``bab" & ``b" \\ -\end{pmatrix} -$$ -\end{example} - - -\begin{definition} -\emph{Взятие элемента по индексу} --- это частный случай взятия подматрицы, когда начало и конец ``среза'' совпадают: -$ -M[i,j] = M[i..i,j..j] -$ -\end{definition} - -\begin{example} -$$ -\begin{pmatrix} -``a" & ``ba" & ``cb" \\ -``ac" & ``bab" & ``b" \\ -\end{pmatrix}[0,1] = ``ba" -$$ -\end{example} - -Из алгебраических операций над матрицами нас в дальнейшем будут интересовать \textit{поэлементные операции}, \textit{скалярные операции}, \textit{матричное умножение}, \textit{произведение Кронекера}. - - -\begin{definition}[Поэлементные операции] - -Пусть $G = (S,\circ)$ --- полугруппа\footnote{Здесь, как и в дальнейшем, требование к структуре быть полугруппой не обязательно. Оно лишь позволяет нам получить ассоциативность соответствующих операций над матрицами, что может оказаться полезным при дальнейшей работе.}, $M_{n \times m}, N_{n\times m}$ --- две матрицы одинакового размера над этой полугруппой. -Тогда -$ -ewise(M,N,\circ) = P_{n \times m} -$ -,такая, что $P[i,j] = M[i,j] \circ N[i,j]$. -\end{definition} - - -\begin{example} - -Пусть $G$ --- полугруппа строк с конкатенацией $\cdot$, - -$$ -M = -\begin{pmatrix} -``a" & ``ba" & ``cb" \\ -``ac" & ``bab" & ``b" \\ -\end{pmatrix}, -$$ - -$$ -N = -\begin{pmatrix} -``c" & ``aa" & ``b" \\ -``a" & ``bac" & ``bb" \\ -\end{pmatrix}. -$$ - -Тогда - -$$ -ewise(M,N, \cdot) = -\begin{pmatrix} -``ac" & ``baaa" & ``cbb" \\ -``aca" & ``babbac" & ``bbb" \\ -\end{pmatrix}. -$$ - - -\end{example} - - -\begin{definition}[Скалярная операция] -Пусть $G = (S,\circ)$ --- полугруппа, $M_{n \times m}$ --- матрица над этой полугруппой, $x \in S$. -Тогда -$ -scalar(M,x,\circ) = P_{n \times m} -$ -, такая, что $P[i,j] = M[i,j] \circ x$, а -$ -scalar(x,M,\circ) = P_{n \times m} -$ -, такая, что $P[i,j] = x \circ M[i,j]$. - -\end{definition} - -\begin{example} - -Пусть $G$ --- полугруппа строк с конкатенацией $\cdot$, $x = ``c"$, - -$$ -M = -\begin{pmatrix} -``a" & ``ba" & ``cb" \\ -``ac" & ``bab" & ``b" \\ -\end{pmatrix}. -$$ - -Тогда -$$ -scalar(M,x, \cdot) = -\begin{pmatrix} -``ac" & ``bac" & ``cbc" \\ -``acc" & ``babc" & ``bc" \\ -\end{pmatrix}, -$$ - -$$ -scalar(x, M, \cdot) = -\begin{pmatrix} -``ca" & ``cba" & ``ccb" \\ -``cac" & ``cbab" & ``cb" \\ -\end{pmatrix}. -$$ - -\end{example} - - -\begin{definition}[Матричное умножение]\label{def:MxM} - -Пусть $G = (S,\oplus, \otimes)$ --- полукольцо, $M_{n \times m}, N_{m\times k}$ --- две матрицы над этим полукольцом. -Тогда -$ -M\cdot N = P_{n \times k} -$ -, такая, что $P[i,j] = \bigoplus_{0 \leq l < m} M[i,l] \otimes N[l,j]$. - -\end{definition} - -\begin{example} -Пусть $G$ --- полукольцо из примера~\ref{exmpl:semiring}, -$$ M = -\begin{pmatrix} -\{``a"\} & \{``a"\}\\ -\{``b"\} & \{``b"\}\\ -\end{pmatrix}, -$$ -$$ N = -\begin{pmatrix} -\{``c"\} \\ -\{``d"\} \\ -\end{pmatrix}. -$$ - -Тогда -$$ -M \cdot N = -\begin{pmatrix} -\{``a" \cdot ``c"\} \cup \{``a" \cdot ``d"\} \\ -\{``b" \cdot ``c"\} \cup \{``b" \cdot ``d"\} -\end{pmatrix}= -\begin{pmatrix} -\{``ac" \ , ``ad"\} \\ -\{``bc" \ , ``bd"\} -\end{pmatrix}. -$$ - -\end{example} - - -\begin{definition}[Произведение Кронекера] -Пусть $G = (S,\circ)$ --- полугруппа, $M_{m\times n}$ и $N_{p\times q}$ --- две матрицы над этой полугруппой. -Тогда произведение Кронекера или тензорное произведение матриц $M$ и $N$ --- это блочная матрица $C$ размера $mp \times nq$, вычисляемая следующим образом: -$$ -C = A \otimes B = -\begin{pmatrix} -scalar(M[0,0],N,\circ) & \cdots & scalar(M[0,n-1],N,\circ) \\ -\vdots & \ddots & \vdots \\ -scalar(M[m-1,0],N,\circ) & \cdots & scalar(M[m-1,n-1],N,\circ) -\end{pmatrix} -$$ - -\end{definition} - -\begin{note}\label{note:KronIsNotCommutative} -Произведение Кронекера не является коммутативным. -При этом всегда существуют две матрицы перестановок $P$ и $Q$ такие, что $A \otimes B = P(B \otimes A)Q$. -\end{note} - -\newcommand{\examplemtrx} -{ -\begin{pmatrix} -5 & 6 & 7 & 8 \\ -9 & 10 & 11 & 12 \\ -13 & 14 & 15 & 16 -\end{pmatrix} -} - -\begin{example} -Возьмём в качестве полугруппы целые числа с умножением. -$$M= -\begin{pmatrix} -1 & 2 \\ -3 & 4 -\end{pmatrix} -$$ -$$N=\examplemtrx -$$ -Тогда -\begin{align} -M \otimes N & = -\begin{pmatrix} -1 & 2 \\ -3 & 4 -\end{pmatrix} -\otimes -\examplemtrx = \notag \\ &= -\begin{pmatrix} -1\examplemtrx & 2\examplemtrx \\ -3\examplemtrx & 4\examplemtrx -\end{pmatrix} -=\notag \\ -&= -\left(\begin{array}{c c c c | c c c c} -5 & 6 & 7 & 8 & 10 & 12 & 14 & 16 \\ -9 & 10 & 11 & 12 & 18 & 20 & 22 & 24 \\ -13 & 14 & 15 & 16 & 26 & 28 & 30 & 32 \\ -\hline -15 & 18 & 21 & 24 & 20 & 24 & 28 & 32 \\ -27 & 30 & 33 & 36 & 36 & 40 & 44 & 48 \\ -39 & 42 & 45 & 48 & 52 & 56 & 60 & 64 -\end{array}\right) -\end{align} -\end{example} - - -\section{Теоретическая сложность умножения матриц} - -В рамках такого раздела теории сложности, как мелкозернистая сложность (fine-grained complexity) задача умножения двух матриц оказалась достаточно важной, так как через вычислительную сложность этой задачи можно оценить сложность большого класса различных задач. С примерами таких задач можно ознакомиться в работе~\cite{Williams:2010:SEP:1917827.1918339}. Поэтому рассмотрим алгоритмы нахождения произведения двух матриц более подробно. Далее для простоты мы будем предполагать, что перемножаются две квадратные матрицы одинакового размера $n \times n$. - -Для начала построим наивный алгоритм, сконструированный на основе определении произведения матриц. Такой алгоритм представлен на листинге~\ref{algo:MxM}. Его работу можно описать следующим образом: для каждой строки в первой матрице и для каждого столбца в второй матрице найти сумму произведений соответствующих элементов. Данная сумма будет значением соответствующей ячейки результирующей матрицы. - -\begin{algorithm} - \floatname{algorithm}{Listing} -\begin{algorithmic}[1]\label{algo:MxM} -\caption{Наивное перемножение матриц} -\Function{MatrixMult}{$M_1, M_2, G=(S,\oplus,\otimes)$} - \State{$M_3 =$ empty matrix of size $n \times n$} - \For {$i \in 0..n-1$} - \For {$j \in 0..n-1$} - \For {$k \in 0..n-1$} - \State{$M_3[i,j] = M_3[i,j] \oplus ( M_1[i,k] \otimes M_2[k,j])$} - \EndFor - \EndFor - \EndFor - \State{\Return $M_3$} - -\EndFunction -\end{algorithmic} -\end{algorithm} - -Сложность наивного произведения двух матриц составляет $O(n^3)$ из-за тройного вложенного цикла, где каждый уровень вложенности привносит $n$ итераций. Но можно ли улучшить этот алгоритм? Первый положительный ответ был опубликовал Ф. Штрассен в 1969 году~\cite{Strassen1969}. Сложность предложенного им алгоритма --- $O(n^{\log_2 7}) \approx O(n^{2.81})$. Основная идея --- рекурсивное разбиение исходных матриц на блоки и вычисление их произведения с помощью только 7 умножений, а не 8. - -Рассмотрим алгоритм Штрассена более подробно. Пусть $A$ и $B$ --- две квадратные матрицы размера $2^n \times 2^n$ над кольцом $R=(S,\oplus,\otimes)$. Если размер умножаемых матриц не является натуральной степенью двойки, то дополняем исходные матрицы дополнительными нулевыми строками и столбцами. Наша задача найти матрицу $C = A \cdot B$. - -Разделим матрицы $A, B$ и $C$ на четыре равные по размеру блока. -$$ -A = -\begin{pmatrix} - A_{1,1} & A_{1,2} \\ - A_{2,1} & A_{2,2} - \end{pmatrix} \mbox{ , } - B = - \begin{pmatrix} - B_{1,1} & B_{1,2} \\ - B_{2,1} & B_{2,2} - \end{pmatrix} \mbox{ , } - C = - \begin{pmatrix} - C_{1,1} & C_{1,2} \\ - C_{2,1} & C_{2,2} - \end{pmatrix} -$$ - -По определению произведения матриц выполняются следующие равенства. -\begin {align*} -C_{1,1}&= A_{1,1} \cdot B_{1,1} + A_{1,2} \cdot B_{2,1} \\ -C_{1,2}&= A_{1,1} \cdot B_{1,2} + A_{1,2} \cdot B_{2,2} \\ -C_{2,1}&= A_{2,1} \cdot B_{1,1} + A_{2,2} \cdot B_{2,1} \\ -C_{2,2}&= A_{2,1} \cdot B_{1,2} + A_{2,2} \cdot B_{2,2} -\end {align*} - -Данная процедура не даёт нам ничего нового с точки зрения вычислительной сложности. Но мы можем двинуться дальше и определить следующие элементы. - -\begin {align*} -P_1 & \equiv (A_{1,1} + A_{2,2}) \cdot (B_{1,1} + B_{2,2}) \\ -P_2 & \equiv (A_{2,1} + A_{2,2}) \cdot B_{1,1} \\ -P_3 & \equiv A_{1,1} \cdot (B_{1,2} - B_{2,2}) \\ -P_4 & \equiv A_{2,2} \cdot (B_{2,1} - B_{1,1}) \\ -P_5 & \equiv (A_{1,1} + A_{1,2}) \cdot B_{2,2} \\ -P_6 & \equiv (A_{2,1} - A_{1,1}) \cdot (B_{1,1} + B_{1,2}) \\ -P_7 & \equiv (A_{1,2} - A_{2,2}) \cdot (B_{2,1} + B_{2,2}) -\end {align*} - -Используя эти элементы мы можем выразить блоки результирующей матрицы следующим образом. - -\begin {align*} -C_{1,1} & = P_1 + P_4 - P_5 + P_7 \\ -C_{1,2} & = P_3 + P_5 \\ -C_{2,1} & = P_2 + P_4 \\ -C_{2,2} & = P_1 - P_2 + P_3 + P_6 -\end {align*} - -При таком способе вычисления мы получаем на одно умножение подматриц меньше, чем при наивном подходе. Это и приводит, в конечном итоге, к улучшению сложности всего алгоритма, который основывается на рекурсивном повторении проделанной выше процедуры. - -Впоследствии сложность постепенно понижалась в ряде работ, таких как ~\cite{Pan1978,BiniCapoRoma1979,Schonhage1981,CoppWino1982,CoppWino1990}. Было введено специальное обозначение для показателя степени в данной оценке: $\omega$. То есть сложность умножения матриц --- это $O(n^\omega)$, и задача сводится к уменьшению значения $\omega$. В настоящее время работа над уменьшением показателя степени продолжается и сейчас уже предложены решения с $\omega < 2.373$\footnote{В данной области достаточно регулярно появляются новые результаты, дающие сравнительно небольшие, в терминах абсолютных величин, изменения. Так, в 2021 была представлена работа, улучшающая значение $\omega$ в пятом знаке после запятой~\cite{alman2020refined}. Несмотря на кажущуюся несерьёзность результата, подобные работы имеют большое теоретическое значение, так как улучшают наше понимание исходной задачи и её свойств.}. - -Всё тем же Ф. Штрассеном ещё в 1969 году была выдвинута гипотеза о том, что для достаточно больших $n$ существует алгоритм, который для любого сколь угодно маленького наперёд заданного $\varepsilon$ перемножает матрицы за $O(n^{2+\varepsilon})$. На текущий момент ни доказательства, ни опровержения этой гипотезы не предъявлено. - -Важной особенностью указанного выше направления улучшения алгоритмов является то, что оно допускает использования (и даже основывается на использовании) более богатых алгебраических структур, чем требуется для определения умножения двух матриц. Так, уже алгоритм Штрасеена использует операцию вычитания, что приводит к необходимости иметь обратные элементы по сложению, а значит определять матрицы над кольцом. Хотя для исходного определения (\ref{def:MxM}) достаточно более бедной структуры. При этом, часто, структуры, возникающие в прикладных задачах кольцами не являются. Примерами могут служить тропическое (или $\{min,+\}$) полукольцо, играющее ключевую роль в тропической математике, или булево ($\{\vee,\wedge\}$) полукольцо, возникающее, например, при работе с отношениями\footnote{Вообще говоря, в некоторых прикладных задачах возникают структуры, не являющиеся даже полукольцом. Предположим, что есть три различных множества $S_1, S_2$ и $S_3$ и две двухместные функции $f:S_1 \times S_2 \to S_3$ и $g: S_3 \times S_3 \to S_3$. Этого достаточно, чтобы определить произведение двух матриц $M_1$ и $M_2$, построенных из элементов множеств $S_1$ и $S_2$ соответственно. Результирующая матрица будет состоять из элементов $S_3$. Как видно, функции не являются бинарными операциями в смысле нашего определения. Несмотря на кажущуюся экзотичность, подобные структуры возникают на практике при работе с графами и учитываются, например, в стандарте GraphBLAS (\url{https://graphblas.github.io/}), где, кстати, называются полукольцами, что выглядит не вполне корректно.}. Значит, описанные выше решения не применимы и вопрос о существовании алгоритма с менее чем кубической сложностью снова актуален. - -В попытках ответить на этот вопрос появились так называемые комбинаторные алгоритмы умножения матриц\footnote{В противовес описанным выше, не являющимся комбинаторными. Стоит отметить, что строгое определение комбинаторных алгоритмов отсутствует, хотя этот термин и получил широкое употребление. В частности, Н.~Бансал (Nikhil Bansal) и Р.~Уильямс (Ryan Williams) в работе~\cite{5438580} дают определение комбинаторного алгоритма, но тут же замечают следующее: ``We would like to give a definition of ``combinatorial algorithm'', but this appears elusive. Although the term has been used in many of the cited references, nothing in the literature resembles a definition. For the purposes of this paper, let us think of a ``combinatorial algorithm'' simply as one that does not call an oracle for ring matrix multiplication.''. Ещё один вариант определения и его обсуждение можно найти в~\cite{das2018lower}.}. Классический результат в данной области --- это алгоритм четырёх русских, предложенный В. Л. Арлазаровым, Е. А. Диницем, М. А. Кронродом и И. А. Фараджевым в 1970 году~\cite{ArlDinKro70}, позволяющий перемножить матрицы над конечным полукольцом за $O(n^3/\log n)$. Лучшим результатом\footnote{В работе~\cite{das2018lower} предложен алгоритм со сложностью $\Omega(n^{7/3}/2^{O(\sqrt{\log n})})$, однако авторы утверждают, что сами не уверены в комбинаторности предложенного решения. По-видимому, полученные результаты ещё должны быть проверены сообществом.} в настоящее время является алгоритм со сложностью\footnote{Нотация $\hat{O}$ скрывает $poly(\log\log)$ коэффициенты.} $\hat{O}(n^3/\log^4 n)$~\cite{10.1007/978-3-662-47672-7_89}. - -Как видим, особенности алгебраических структур накладывают серьёзные ограничения на возможности конструирования алгоритмов. Отметим, что, хотя, в указанных случаях и предлагаются решения лучшие, чем наивное кубическое, они обладают принципиально разной асимптотической сложностью. в первом случае сложность оценивается полиномом, степень которого меньше третьей. Такие решения принято называть \textit{истинно субкубическими} (truly subcubic). В то время как в случае комбинаторных алгоритмов степень полинома остается прежней, третьей, хотя сложность и уменьшается на логарифмический фактор. Такие решения принято называть \textit{слегка субкубическими} (mildly subcubic). Естественный вопрос о существовании истинно субкубического алгоритма перемножения матриц над полукольцами (или же комбинаторного перемножения матриц) всё ещё не решён\footnote{Один из кандидатов --- работа~\cite{das2018lower}, однако на текущий момент предложенное в ней решение требует проверки.}. - -%Заметим, что скалярная операция --- это частный случай произвеления Кронекера: достаточно превратить элемент носителя полугруппы в матрицу размера $1\times 1$. - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item Привидите примеры некоммутативных операций. -% \item Привидите примеры ситуаций, когда наличие у бинарных операций каких-либо дополнитльных свойств (ассоциативности, коммутативности), позволяет строить более эффективные алгоритмы, чем в общем случае. -%\end{enumerate} diff --git a/tex/List_of_contributors.tex b/tex/List_of_contributors.tex deleted file mode 100644 index 66b0e68..0000000 --- a/tex/List_of_contributors.tex +++ /dev/null @@ -1,30 +0,0 @@ -\chapter*{Список авторов\markboth{Введение}{Список авторов}} -%\begin{multicols}{2} - \begin{itemize} - \item \textbf{Семён Григорьев} \\ - Санкт-Петербургский государственный университет, Университетская набережная, 7/9, Санкт-Петербург, 199034, Россия \\ - \url{s.v.grigoriev@spbu.ru}\\ - \\ - JetBrains Research, Приморский проспект 68-70, здание 1, Санкт-Петербург, 197374, Россия \\ - \url{semyon.grigorev@jetbrains.com} - - - \item \textbf{Екатерина Вербицкая} \\ -% Санкт-Петербургский государственный университет \\ -% Университетская набережная, 7/9 \\ -% Санкт-Петербург, 199034, Россия \\ -% \url{s.v.grigoriev@spbu.ru}\\ -% \\ - JetBrains Research, Приморский проспект 68-70, здание 1, Санкт-Петербург, 197374, Россия \\ - \url{ekaterina.verbitskaya@jetbrains.com} - - - \item \textbf{Дмитрий Кутленков} \\ - Санкт-Петербургский государственный университет, Университетская набережная, 7/9, Санкт-Петербург, 199034, Россия \\ - \url{kutlenkov.dmitri@gmail.com} - - \item Полный список людей, внёсших свой вклад в данную работу, можно посмотреть на страничке проекта: \\ \small{\href{https://github.com/FormalLanguageConstrainedPathQuerying/FormalLanguageConstrainedReachability-LectureNotes}{https://github.com/FormalLanguageConstrainedPathQuerying/\\FormalLanguageConstrainedReachability-LectureNotes}} - - \end{itemize} -%\end{multicols} - diff --git a/tex/Matrix-based_CFPQ.tex b/tex/Matrix-based_CFPQ.tex deleted file mode 100644 index 6cab06b..0000000 --- a/tex/Matrix-based_CFPQ.tex +++ /dev/null @@ -1,367 +0,0 @@ -\chapter[Контекстно-свободная достижимость через произведение матриц]{Контекстно-свободная достижимость через произведение матриц}\label{chpt:MatrixBasedAlgos} -\chaptermark{КС достижимость через произведение матриц} - -В данном разделе мы рассмотрим алгоритм решения задачи контекстно-свободной достижимости, основанный на произведении матриц. -Будет показано, что при использовании конъюнктивных грамматик, представленный алгоритм находит переапроксимацию истинного решения задачи. - -\section[Алгоритм контекстно-свободной достижимости через произведение матриц]{Алгоритм контекстно-свободной достижимости через произведение матриц\sectionmark{Алгоритм КС достижимости через произведение матриц}} -\sectionmark{Алгоритм КС достижимости через произведение матриц} -\label{Matrix-CFPQ} - -В главе~\ref{graph:CYK}~был изложен алгоритм для решения задачи КС достижимости на основе CYK. -Заметим, что обход матрицы напоминает умножение матриц в ячейках которых множества нетерминалов: -\begin{align*} -M_3 = &M_1 \times M_2 \\ -M_3[i,j] = &\sum_{k=1}^{n} M[i,k] * M[k,j] -\end{align*} -, где сумма --- это объединение множеств: -\[ -\sum_{k=1}^{n} = \bigcup_{k=1}^{n} -\] -, а поэлементное умножение определено следующим образом: -\[ -S_1 * S_2 = \{N_1^0 ... N_1^m\} * \{N_2^0 ... N_2^l\} = \{N_3 \mid (N_3 \rightarrow N_1^i N_2^j) \in P\}. -\] -Таким образом, алгоритм решения задачи КС достижимости может быть выражена в терминах перемножения матриц над полукольцом с соответствующими операциями. - -Для частного случая этой задачи, синтаксического анализа линейного входа, существует алгоритм Валианта~\cite{Valiant:1975:GCR:1739932.1740048}, использующий эту идею. -Однако он не обобщается на графы из-за того, что существенно использует возможность упорядочить обход матрицы (см. разницу в CYK для линейного случая и для графа). -Поэтому, хотя для линейного случая алгоритм Валианта является алгоритмом синтаксического анализа для произвольных КС грамматик за субкубическое время, его обобщение до задачи КС достижимости в произвольных графах с сохранением асимптотики является нетривиальной задачей~\cite{Yannakakis}. -В настоящее время алгоритм с субкубической сложностью получен только для частного случая --- языка Дика с одним типом скобок --- Филипом Брэдфорlом~\cite{8249039}. - -В случае с линейным входом, отдельного внимания заслуживает работа Лиллиан Ли (Lillian Lee)~\cite{Lee:2002:FCG:505241.505242}, где она показывает, что задача перемножения матриц сводима к синтаксическому анализу линейного входа. Аналогичных результатов для графов на текущий момент не известно. - -Поэтому рассмотрим более простую идею, изложенную в статье Рустама Азимова~\cite{Azimov:2018:CPQ:3210259.3210264}: будем строить транзитивное замыкание графа через наивное (не через возведение в квадрат) умножение матриц. - -Пусть $\mathcal{G} = (V, E)$ --- входной граф и $G = (N,\Sigma,P)$ --- входная грамматика. Тогда алгоритм может быть сформулирован, как представлено в листинге~\ref{alg:graphParse}. - -\begin{algorithm}[H] -\begin{algorithmic}[1] -\caption{Context-free recognizer for graphs} -\label{alg:graphParse} -\Function{contextFreePathQuerying}{$\mathcal{G}$, G} - - \State{$n \gets$ количество узлов в $\mathcal{G}$} - \State{$E \gets$ направленные ребра в $\mathcal{G}$} - \State{$P \gets$ набор продукций из $G$} - \State{$T \gets$ матрица $n \times n$, в которой каждый элемент $\varnothing$} - \ForAll{$(i,x,j) \in E$} - \Comment{Инициализация матрицы} - \State{$T_{i,j} \gets T_{i,j} \cup \{A~|~(A \rightarrow x) \in P \}$} - \EndFor - \ForAll{$i \in 0\ldots n-1$} - \Comment{Добавление петель для нетерминалов, порождающих пустую строку} - \State{$T_{i,i} \gets T_{i,i} \cup \{ A \in N \mid A \to \varepsilon \}$} - \EndFor - \While{матрица $T$ меняется} - - \State{$T \gets T \cup (T \times T)$} - \Comment{Вычисление транзитивного замыкания} - \EndWhile -\State \Return $T$ -\EndFunction -\end{algorithmic} -\end{algorithm} - - -\begin{example}[Пример работы] - -Пусть есть граф $\mathcal{G}$: -\begin{center} - \input{figures/graph/graph0.tex} -\end{center} - -и грамматика $G$: -\begin{align*} -S &\to A B &A \to a \\ -S &\to A S_1 &B \to b\\ -S_1 &\to S B -\end{align*} - - -Пусть $T_i$ --- матрица, полученная из $T$ после применения цикла, описанного в строках \textbf{8-9} алгоритма~\ref{alg:graphParse}, $i$ раз. -Тогда $T_0$, полученная напрямую из графа, выглядит следующим образом: - -\[ -T_0 = \begin{pmatrix} - \varnothing & \{A\} & \varnothing & \{B\} \\ - \varnothing & \varnothing & \{A\} & \varnothing \\ - \{A\} & \varnothing & \varnothing & \varnothing \\ - \{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} -\] - -Далее показано получение матрицы $T_1$. - -\[ -T_0 \times T_0 = \begin{pmatrix} - \varnothing & \varnothing & \varnothing & \varnothing \\ - \varnothing & \varnothing & \varnothing & \varnothing \\ - \varnothing & \varnothing & \varnothing & \{S\} \\ - \varnothing & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} -\] - -\[ -T_1 = T_0 \cup (T_0 \times T_0) = \begin{pmatrix} - \varnothing & \{A\} & \varnothing & \{B\} \\ - \varnothing & \varnothing & \{A\} & \varnothing \\ - \{A\} & \varnothing & \varnothing & \cellcolor{lightgray} \{\pmb{S}\} \\ - \{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} -\] - -После первой итерации цикла нетерминал в ячейку $T[2,3]$ добавился нетерминал $S$. -Это означает, что существует такой путь $\pi$ из вершины 2 в вершину 3 в графе $\mathcal{G}$, что $S \xrightarrow{*} \omega(\pi)$. В данном примере путь состоит из двух ребер $2 \xrightarrow{a} 0$ и $ 0 \xrightarrow{b} 3$, так что $S \xrightarrow{*} ab$. - -Вычисление транзитивного замыкания заканчивается через $k$ итераций, когда достигается неподвижная точка процесса: $T_{k-1} = T_k$. Для данного примера $k = 13$, так как $T_{13} = T_{12}$. Весь процесс работы алгоритма (все матрицы $T_i$) показан ниже (на каждой итерации новые элементы выделены жирным). - -{\footnotesize -\begin{alignat*}{7} -& &&T_2 &&= \begin{pmatrix} -\varnothing & \{A\} & \varnothing & \{B\} \\ -\varnothing & \varnothing & \{A\} & \varnothing \\ -\cellcolor{lightgray} \{A, \pmb{S_1}\} & \varnothing & \varnothing & \{S\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} \ \ \ \ &&T_3 &&= \begin{pmatrix} -\varnothing & \{A\} & \varnothing & \{B\} \\ -\cellcolor{lightgray} \{\pmb{S}\} & \varnothing & \{A\} & \varnothing \\ -\{A, S_1\} & \varnothing & \varnothing & \{S\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} \\ & &&T_4 &&= \begin{pmatrix} -\varnothing & \{A\} & \varnothing & \{B\} \\ -\{S\} & \varnothing & \{A\} & \cellcolor{lightgray} \{\pmb{S_1}\} \\ -\{A, S_1\} & \varnothing & \varnothing & \{S\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} \ \ \ \ &&T_5 &&= \begin{pmatrix} -\varnothing & \{A\} & \varnothing & \cellcolor{lightgray} \{B, \pmb{S}\} \\ -\{S\} & \varnothing & \{A\} & \{S_1\} \\ -\{A, S_1\} & \varnothing & \varnothing & \{S\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} \\ & &&T_6 &&= \begin{pmatrix} -\cellcolor{lightgray} \{\pmb{S_1}\} & \{A\} & \varnothing & \{B, S\} \\ -\{S\} & \varnothing & \{A\} & \{S_1\} \\ -\{A, S_1\} & \varnothing & \varnothing & \{S\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} \ \ \ \ &&T_7 &&= \begin{pmatrix} -\{S_1\} & \{A\} & \varnothing & \{B, S\} \\ -\{S\} & \varnothing & \{A\} & \{S_1\} \\ -\cellcolor{lightgray} \{A, S_1, \pmb{S}\} & \varnothing & \varnothing & \{S\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} \\ -& &&T_8 &&= \begin{pmatrix} -\{S_1\} & \{A\} & \varnothing & \{B, S\} \\ -\{S\} & \varnothing & \{A\} & \{S_1\} \\ -\{A, S_1, S\} & \varnothing & \varnothing & \cellcolor{lightgray} \{S, \pmb{S_1}\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} \ \ \ \ &&T_9 &&= \begin{pmatrix} -\{S_1\} & \{A\} & \varnothing & \{B, S\} \\ -\{S\} & \varnothing & \{A\} & \cellcolor{lightgray} \{S_1, \pmb{S}\} \\ -\{A, S_1, S\} & \varnothing & \varnothing & \{S, S_1\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} \\ & &&T_{10} &&= \begin{pmatrix} -\{S_1\} & \{A\} & \varnothing & \{B, S\} \\ -\cellcolor{lightgray} \{S, \pmb{S_1}\} & \varnothing & \{A\} & \{S_1, S\} \\ -\{A, S_1, S\} & \varnothing & \varnothing & \{S, S_1\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} \ \ \ \ &&T_{11} &&= \begin{pmatrix} -\cellcolor{lightgray} \{S_1, \pmb{S}\} & \{A\} & \varnothing & \{B, S\} \\ -\{S, S_1\} & \varnothing & \{A\} & \{S_1, S\} \\ -\{A, S_1, S\} & \varnothing & \varnothing & \{S, S_1\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} \\ & &&T_{12} &&= \begin{pmatrix} -\{S_1, S\} & \{A\} & \varnothing & \cellcolor{lightgray} \{B, S, \pmb{S_1}\} \\ -\{S, S_1\} & \varnothing & \{A\} & \{S_1, S\} \\ -\{A, S_1, S\} & \varnothing & \varnothing & \{S, S_1\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} \ \ \ \ &&T_{13} &&= \begin{pmatrix} -\{S_1, S\} & \{A\} & \varnothing & \{B, S, S_1\} \\ -\{S, S_1\} & \varnothing & \{A\} & \{S_1, S\} \\ -\{A, S_1, S\} & \varnothing & \varnothing & \{S, S_1\} \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} -\end{alignat*} -} - -Таким образом, результат алгоритма~\ref{alg:graphParse} для нашего примера --- это матрица $T_{13} = T_{12}$. Заметим, что для данного алгоритма приведённый пример также является худшим случаем: на каждой итерации в матрицу добавляется ровно один нетерминал, при том, что необходимо заполнить порядка $O(n^2)$ ячеек. - -\end{example} - - -\subsection{Расширение алгоритма для конъюнктивных грамматик} - -Матричный алгоритм для конъюнктивных грамматик отличается от алгоритма~\ref{alg:graphParse} для контекстно-свободных грамматик только операцией умножения матриц, в остальном алгоритм остается без изменений. Определим операцию умножения матриц. -\begin{definition} - Пусть $M_1$ и $M_2$ матрицы размера $n$. Определим операцию $\circ$ следующим образом: - \[M_1 \circ M_2 = M_3,\] - \[M_3 [i,j] = \{A \mid \exists (A \rightarrow B_1 C_1 \& \ldots \& B_m C_m) \in P, (B_k , C_k) \in d[i,j] \forall k = 1,\ldots,m\}\], - где \[d[i,j] = \bigcup_{k = 1}^{n} M_1 [i,k] \times M_2 [k,j].\] -\end{definition} - -Важно заметить, что алгоритм для конъюнктивных грамматик, в отличие от алгоритма для контекстно-свободных грамматик, дает лишь верхнюю оценку ответа. То есть все нетерминалы, которые должны быть в ячейках матрицы результата, содержатся там, но вместе с ними содержатся и лишние нетерминалы. Рассмотрим пример, иллюстрирующий появление лишних нетерминалов. - -\begin{example} - Грамматика $G$: - \begin{align*} - S &\to AB \& DC & C &\to c \\ - A &\to a & D &\to DC \mid b\\ - B &\to BC \mid b - \end{align*} - Очевидно, что грамматика $G$ задает язык из одного слова $L(G) = \{abc\} = \{abc^*\} \cap \{a^* bc\}$. - - Пусть есть граф $\mathcal{G}$: - \begin{center} - \input{figures/multi/graph0.tex} - \end{center} - Применяя алгоритм, получим, что существует путь из вершины 0 в вершину 4, выводимый из нетерминала $S$. Однако очевидно, что в графе такого пути нет. - Такое поведение алгоритма наблюдается из-за того, что существует путь ``abcc'', соответствующий $L(AB) = \{abc^*\}$ и путь ``aabc'', соответствующий $L(DC) = \{a^{*}bc\}$, но они различны. Однако алгоритм не может это проверить, так как оперирует понятием достижимости между вершинами, а не наличием различных путей. Более того, в общем случае для конъюнктивных грамматик такую проверку реалиховать нельзя. Поэтому для классической семантики достидимости с ограничениями в терминах конъюнктивных грамматик результат работы алгоритма является оценкой сверху. - - Существует альтернативная семантика, когда мы трактуем конъюнкцию в правой части правил как конъюнкцию в Datalog (подробнее о Datalog в параграфе~\ref{Subsection Datalog}). Т.е если есть правило $S \to AB \& DC$, то должен быть путь принадлежащий языку $L(AB)$ и путь принадлежащий языку $L(DC)$. В такой семантике алгоритм дает точный ответ. -\end{example} - -Подробнее алгоритм описан в статье Рустама Азимова и Семёна Григорьева~\cite{565CECD7E8F5C6063935B41DB41797AA37D53B04}. Стоит также отметить, что обобщения данного алгоритма для булевых грамматик не существует, хотя и существует частное решение для случая, когда граф не содержит циклов (является DAG-ом), предложенное Екатериной Шеметовой~\cite{Shemetova2019}. - -\section{Особенности реализации} - -Алгоритмы, описанные выше, удобны с точки зрения реализации тем, что могут быть эффективно реализованы с использованием высокопроизводительных библиотек линейной алгебры, которые эксплуатируют возможности параллельных вычислений на современных CPU и GPGPU~\cite{Mishin:2019:ECP:3327964.3328503}. -Это позволяет с минимальными затратами получить эффективную параллельную реализацию алгоритма для решения задачи КС достижимости в графах. -Благодаря этому, хотя асимптотически приведенные алгоритмы имеют большую сложность чем, скажем, алгоритм Хеллингса, в результате эффективного распараллеливания на практике они работают быстрее однопоточных алгоритмов с лучшей сложностью. - -Далее рассмотрим некоторые детали, упрощающие реализацию с использованием современных библиотек и аппаратного обеспечения. - -Так как множество нетерминалов и правил конечно, то мы можем свести представленный выше алгоритм к булевым матрицам: для каждого нетерминала заведём матрицу, такую что в ячейке стоит 1 тогда и только тогда, когда в исходной матрице в соответствующей ячейке содержится этот нетерминал. -Тогда перемножение пары таких матриц, соответствующих нетерминалам $A$ и $B$, соответствует построению путей, выводимых из нетерминалов, для которых есть правила с правой частью вида $A B$. - -\begin{example} -Представим в виде набора булевых матриц следующую матрицу: -\[ -T_0 = \begin{pmatrix} -\varnothing & \{A\} & \varnothing & \{B\} \\ -\varnothing & \varnothing & \{A\} & \varnothing \\ -\{A\} & \varnothing & \varnothing & \varnothing \\ -\{B\} & \varnothing & \varnothing & \varnothing \\ -\end{pmatrix} -\] - -Тогда: -\begin{alignat*}{7} -& &&T_{0\_A} &&= \begin{pmatrix} -0 & 1 & 0 & 0 \\ -0 & 0 & 1 & 0 \\ -1 & 0 & 0 & 0 \\ -0 & 0 & 0 & 0 \\ -\end{pmatrix} \ \ \ \ &&T_{0\_B} &&= \begin{pmatrix} -0 & 0 & 0 & 1 \\ -0 & 0 & 0 & 0 \\ -0 & 0 & 0 & 0 \\ -1 & 0 & 0 & 0 \\ -\end{pmatrix} -\end{alignat*} -Тогда при наличии правила $S \to A B$ в грамматике получим: -\[ -T_{1\_S} =T_{0\_A} \times T_{0\_B} = \begin{pmatrix} -0 & 0 & 0 & 0 \\ -0 & 0 & 0 & 0 \\ -0 & 0 & 0 & 1 \\ -0 & 0 & 0 & 0 \\ -\end{pmatrix} -\] -\end{example} - -Алгоритм же может быть переформулирован так, как показано в листинге~\ref{lst:cfpq_mtx_bool}. -Такой взгляд на алгоритм позволяет использовать для его реализации существующие высокопроизводительные библиотеки для работы с булевыми матрицами (например M4RI\footnote{M4RI --- одна из высокопроизводительных библиотек для работы с логическими матрицами на CPU. Реализует Метод Четырёх Русских. Исходный код библиотеки: \url{https://bitbucket.org/malb/m4ri/src/master/}. Дата посещения: 30.03.2020.}~\cite{DBLP:journals/corr/abs-0811-1714}) или библиотеки для линейной алгебры (например CUSP~\cite{Cusp}). - -\begin{algorithm} - \floatname{algorithm}{Listing} -\begin{algorithmic}[1] -\caption{Context-free path querying algorithm. Boolean matrix version} -\label{lst:cfpq_mtx_bool} -\Function{evalCFPQ}{$D=(V,E), G=(N,\Sigma,P)$} - \State{$n \gets$ |V|} - \State{$T \gets \{T^{A_i} \mid A_i \in N, T^{A_i}$ is a matrix $n \times n$, $T^{A_i}_{k,l} \gets$ \texttt{false}\} } - \ForAll{$(i,x,j) \in E$, $A_k \mid A_k \to x \in P$} - %\Comment{Matrices initialization} - %\For{$A_k \mid A_k \to x \in P$} - {$T^{A_k}_{i,j} \gets \texttt{true}$} - %\EndFor - \EndFor - \For{$A_k \mid A_k \to \varepsilon \in P$} - {$T^{A_k}_{i,i} \gets \texttt{true}$} - \EndFor - - \While{any matrix in $T$ is changing} - %\Comment{Transitive closure calculation} - \For{$A_i \to A_j A_k \in P$} - { $T^{A_i} \gets T^{A_i} + (T^{A_j} \times T^{A_k})$ } - \EndFor - \EndWhile -\State \Return $T$ -\EndFunction -\end{algorithmic} -\end{algorithm} - -С другой стороны, для запросов, выразимых в терминах грамматик с небольшим количеством нетерминалов, практически может быть выгодно представлять множества нетерминалов в ячейке матрицы в виде битового вектора следующим образом. -Нумеруем все нетерминалы с нуля, в векторе стоит 1 на позиции $i$, если в множестве есть нетерминал с номером $i$. -Таким образом, в каждой ячейке хранится битовый вектор длины $|N|$. -Тогда операция умножения определяется следующим образом: -\[v_1 \times v_2 = \{v \mid \exists (v,v_3) \in P, \textit{append}(v_1, v_2) \& v_3 = v_3\},\] где $\&$ --- побитовое \texttt{``и''}. - -Правила надо кодировать соответственно: продукция это пара, где первый элемент --- битовый вектор длины $|N|$ с единственной единицей в позиции, соответствующей нетерминалу в правой части, а второй элемент --- вектор длины $2|N|$, с двумя единицами кодирующими первый и второй нетерминалы. - -\begin{example} -Пусть $N = \{S, A, B\}$ и в грамматике есть продукция $S \to A B$. Тогда занумеруем нетерминалы $ (S, 0), (A, 1), (B, 2)$. Продукция примет вид $[1, 0, 0] \to [0, 1, 0, 0, 0, 1]$. Матрица $T_0$ примет вид (здесь ``$.$'' означает, что в ячейке стоит $[0,0,0]$): -\[ -T_0 = \begin{pmatrix} -. & [0,1,0] & . & [0,0,1] \\ -. & . & [0,1,0] & . \\ -[0,1,0] & . & . & . \\ -[0,0,1] & . & . & . \\ -\end{pmatrix} -\] - -После выполнения умножения получим: -\[ -T_1 = T_0 + T_0 \times T_0 = -\begin{pmatrix} -. & [0,1,0] & . & [0,0,1] \\ -. & . & [0,1,0] & . \\ -[0,1,0] & . & . & \cellcolor{lightgray}[1,0,0] \\ -[0,0,1] & . & . & . \\ -\end{pmatrix} -\] -\end{example} - - -На практике в роли векторов могут выступать беззнаковые целые числа. -Например, 32 бита под ячейки в матрице и 64 бита под правила (или 8 и 16, если позволяет количество нетерминалов в грамматике, или 16 и 32). -Тогда умножение выражается через битовые операции и сравнение, что довольно эффективно с точки зрения вычислений. - -Для небольших запросов такой подход к реализации может оказаться быстрее: в данном случае скорость зависит от деталей. -Минус подхода в том, что нет возможности использовать готовые библиотеки линейной алгебры без предварительной модификации. -Только если они не являются параметризуемыми и не позволяют задать собственный тип и собственную операцию умножения и сложения (иными словами, собственное полукольцо). -Такую возможность предусматривает, например, стандарт GraphBLAS\footnote{GraphBLAS --- открытый стандарт, описывающий набор примитивов и операций, необходимый для реализации графовых алгоритмов в терминах линейной алгебры. Web-страница проекта: \url{https://github.com/gunrock/graphblast}. Дата доступа: 30.03.2020.} и, соответственно, его реализации, такие как SuiteSparse\footnote{SuiteSparse --- это специализированное программное обеспечения для работы с разреженными матрицами, которое включает в себя реализацию GraphBLAS API. Web-страница проекта: \url{http://faculty.cse.tamu.edu/davis/suitesparse.html}. Дата доступа: 30.03.2020.}~\cite{Davis2018Algorithm9S}. - -Также стоит заметить, что при работе с реальными графами матрицы, как правило, оказываются разреженными, а значит необходимо использовать соответствующие представления матриц (CRS, покоординатное, Quad Tree~\cite{quadtree}) и библиотеки, работающие с таким представлениями. - -Однако даже при использовании разреженных матриц, могут возникнуть проблемы с размером реальных данных и объёмом памяти. -Например, для вычислений на GPGPU лучше всего, когда все нужные для вычисления матрицы помещаются на одну карту. -Тогда можно свести обмен данными между хостом и графическим сопроцессором к минимуму. -Если не помещаются все, то нужно, чтобы помещалась хотя бы тройка непосредственно обрабатываемых матриц (два операнда и результат). -В самом тяжёлом случае в памяти не удаётся разместить даже операнды целиком и тогда приходится прибегать к поблочному умножению матриц. - -Отдельной инженерной проблемой является масштабирование алгоритмов на несколько вычислительных узлов, как на несколько CPU, так и на несколько GPGPU. - -Важным свойством рассмотренного алгоритма является то, что описанные проблемы с объёмом памяти и масштабированием могут эффективно решаться в рамках библиотек линейной алгебры общего назначения, что избавляет от необходимости создавать специализированные решения для конкретных задач. - - -\section{От нескольких стартовых вершин} - -Статья:~\cite{Terekhov2021MultipleSourceCP} - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item Находить кратчайшие пути в графах, используя идеи из секции~\ref{Matrix-CFPQ}. -% \item Превратить граф, использующийся для CFPQ, в дерево. -% \item Реализовать предложенные идеи на различных архитектурах. -% \item Замерить производительность и расходы памяти по сравнению с существующими реализациями. -%\end{enumerate} diff --git a/tex/Multiple_Context-Free_Language_Reachability.tex b/tex/Multiple_Context-Free_Language_Reachability.tex deleted file mode 100644 index cc81ba5..0000000 --- a/tex/Multiple_Context-Free_Language_Reachability.tex +++ /dev/null @@ -1,401 +0,0 @@ -\chapter{Поиск путей с ограничениями в терминах многокомпонентных контекстно-свободных языков} - -%В статтическом анализе кода --- ещё одна аппроксимация. Например, On. Есть ли точно описываемые задачи? - -%Алгоритм на матрицах - -Создание алгоритмов поиска путей с ограничениями в терминах многокомпонентных контекстно-свободных языков позволяет использовать более сложные графовые запросы. Такие алгоритмы могут найти применение в различных областях, например, в статическом анализе кода. На практике, одним из наиболее широко используемых КС-языков в задачах поиска путей в графе является язык Дика~\cite{zhang2013fast,kodumal2004set} правильных скобочных последовательностей. В частности, в статическом анализе программ этот язык используется для \textit{context-sensitive} или \textit{data-dependence} анализа~\cite{reps2000undecidability}. А именно, в \textit{context-sensitive} анализе моделируется сбалансированность вызовов и выходов из процедур с использованием открывающих и закрывающих скобок. Аналогично, в \textit{data-dependence} анализе используется какое-то одно сбалансированное свойство конструкторов языка, например, обращения к полям (т.е. чтения и записи~\cite{bastani2015specification,yan2011demand}), перенаправления указателей (т.е. ссылки и разыменования~\cite{zheng2008demand}) и т.д. Однако точный анализ, охватывающий два или более сбалансированных свойств является неразрешимой задачей~\cite{reps2000undecidability}. Например, \textit{context-sensitive} и \textit{data-dependence} анализ описывается шафлом языков Дика, и этот язык не является контекстно-свободным. Традиционный подход в таком случае заключается в аппроксимации решения с помощью алгоритмов КС-достижимости. Шафл языков Дика можно рассматривать как пересечение двух КС-языков. Однако КС-языки не замкнуты относительно операции пересечения~\cite{Hopcroft+Ullman/79/Introduction}. Поэтому приходится жертвовать точностью для одного из сбалансированных свойств, т.е. один из языков Дика для \textit{context-sensitive} или \textit{data-dependence} анализа аппроксимируется регулярным языком~\cite{huang2015scalable,sridharan2006refinement}. - -Однако для более точного анализа можно использовать и другие классы формальных языков. Например, \textit{линейные конъюнктивные языки} (LCL) могут применяться для \textit{context-sensitive} и \textit{data-dependence} анализа, причём демонстрируют значительные преимущества такого подхода в точности и масштабируемости~\cite{zhang2017context}. Таким образом, класс \textit{многокомпонентных контекстно-свободных языков} (MCFL) также может содержать языки, которые могут быть использованы для повышения точности решения некоторых задач статического анализа программ программного. Одним из кандидатов на место такого языка является язык $O_n$, который может моделировать согласованное количество открывающих и закрывающих скобок для \textit{context-sensitive} и \textit{data-dependence} анализа. Эти языки являются аппроксимациями шафлов языков Дика и, как известно, не являются контекстно-свободными. Например, $O_2=\{\omega \in \{a,\overline{a},b,\overline{b}\}^* \mid |\omega|_a=|\omega|_{\overline{a}} \wedge |w|_b=|w|_{\overline{b}}\}$. - - -Известно, что задача поиска путей с ограничениями в терминах многокомпонентных контекстно-свободных языков разрешима, поскольку MCFL замкнуты относительно пересечения с регулярными языками (т.е. с графами) и информация о достижимости может быть вычислена путем проверки полученного языка на пустоту, что является разрешимой задачей~\cite{seki1991multiple}. - -На практике хорошим приёмом для получения высокопроизводительных решений задач анализа графов является выражение наиболее критичных вычислений через операции линейной алгебры, например, через матричные операции~\cite{doi:10.1137/1.9780898719918}. Существуют эффективные алгоритмы парсинга для MCFL на основе линейной алгебры, использующие умножения булевых матриц~\cite{nakanishi1997efficient,cohen2016parsing} и способные лечь в основу новых алгоритмов MCFL-достижимости. Однако алгоритм в работе~\cite{cohen2016parsing} может быть применен только для некоторого подкласса многокомпонентных контекстно-свободных грамматик, называемого \textit{несбалансированными}. Поэтому далее в этой главе будет приведён алгоритм поиска путей с ограничениями в терминах многокомпонентных контекстно-свободных языков, основанный на алгоритме из работы~\cite{nakanishi1997efficient}. - - -\section{Нормальная форма MCFG}\label{normalformmcfg} -Сперва мы введём следующую нормальную форму для MCFG, которая позволяет решать задачу MCFL-достижимости с помощью операций линейной алгебры. - -\begin{definition} m-MCFG $G = (\Sigma, N, S, P)$ находится в \emph{нормальной форме}, если любое правило $p: A \rightarrow (\gamma_1, \dots, \gamma_{dim(A)}) \in P$ satisfies соответсвует одной из следующих форм. - \begin{itemize} - %\item $\forall i: 1 \leq i \leq d(A) \ \ \gamma_i \neq \varepsilon$ - \item $\forall i: |\gamma_i| = 1$ и $\gamma_i \in \Sigma \cup \{\varepsilon\}$. - \item $\forall i: \gamma_i \in N_c^*$, т.е. в правой части правила нету терминальных символов. Для простоты будем обозначать такие правила $p: A \rightarrow f(B_1, \dots, B_n)$, где $B_k \in N$. В таком случае необходимо, чтобы $n = 2$. В итоге, имеем правила вида $p: A \rightarrow f(B_1, B_2)$, где $B_1, B_2 \in N$. Для таких правил также должно выполнятся следующее. - \begin{itemize} - \item \textbf{Non-erasing condition}:$\forall i \in \{1,2\}, 1 \leq j \leq d(B_i)$ $B_i^j$ используется в $\gamma_k$ для некоторого $k$, - \item никакая пара символов $B^j, B^k$, являющихся компонентами одного и того нетерминала, не присутствует в правой части правила подряд, т.е. компоненты нетерминалов $B_1, B_2$ чередуются, - \item $\exists i: 1 \leq i \leq d(A) \ \ |\gamma_i| \geq 2$. - \end{itemize} - \end{itemize} -\end{definition} - -Согласно~\cite{nakanishi1997efficient}, справедлива следующая теорема. - -\begin{theorem}\label{thm:formofmcfg} - Для любой MCFG $G$ может быть построена MCFG $G'$ такая, что $L(G') = L(G)$ и $G'$ находится в описанной нормальной форме. -\end{theorem} - -Например, для $m = 1$ описанная нормальная форма соответствует ослабленной нормальной форме Хомского для КС-грамматик. - -Пусть имеется MCFG $G_1 = (\Sigma_1, N_1, S, P_1)$, где $\Sigma_1 = \{a,b,c,d\}$, $N_1 = \{S_, A, B\}$, $P_1 = \{$ -\begin{align*} - S^1 \rightarrow A^1 B^1 A^2 B^2 \\ - (A^1, A^2) \rightarrow (a,c) \\ - (B^1, B^2) \rightarrow (b,d) \\ - (B^1, B^2) \rightarrow (bB^1, dB^2) \\ - (A^1, A^2) \rightarrow (aA^1, cA^2) -\end{align*} -$\}.$ - -Такая грамматика порождает один из классических MCFL: $L(G_1) = \{a^nb^mc^nd^m \mid n,m \in \mathbb{N}\}$, который не является контекстно-свободным. - -Тогда грамматика $G'_1$ в нормальной форме может быть построена по грамматике $G_1$, где $L(G'_1) = L(G_1)$ и $N'_1 = \{S, S_1, S_2, A, B, C, D\}$, $P'_1 = \{$ -\begin{align*} - A^1 \rightarrow a \\ - B^1 \rightarrow b \\ - C^1 \rightarrow c \\ - D^1 \rightarrow d \\ - (S_1^1, S_1^2) \rightarrow (a,c) \\ - (S_2^1, S_2^2) \rightarrow (b,d) \\ - (S_1^1, S_1^2) \rightarrow (S_3^1, S_3^2 C^1) \\ - (S_3^1, S_3^2) \rightarrow (A^1 S_1^1, S_1^2) \\ - (S_2^1, S_2^2) \rightarrow (S_4^1, S_4^2 D^1) \\ - (S_4^1, S_4^2) \rightarrow (B^1 S_2^1, S_2^2) \\ - S^1 \rightarrow S_1^1 S_2^1 S_1^2 S_2^2 -\end{align*} -$\}.$ - -\section{Постановка задачи} -Сформулируем задачу MCFL-достижимости. - -\begin{definition} - Пусть дан помеченный граф $D = (V, E, \Sigma)$ и MCFL $L$. Тогда \emph{многокомпонентное контекстно-свободное отношение} для языка $L$ и графа $D$ --- это отношение $R_{D, L} \subseteq V \times V$: - \begin{equation*} \label{eq1} - \begin{split} - R_{D, L} = \{ &(v_0, v_n) \in V \times V \mid \\ &\ \exists \pi = ((v_0, l_1, v_1), \ldots, (v_{n-1}, l_n, v_n)) \in \pi(D): \\ - &\ l(\pi) \in L \}. - \end{split} - \end{equation*} -\end{definition} - -\begin{definition} - \emph{MCFL-достижимость} --- это задача нахождения многокомпонентных контекстно-свободных отношений $R_{D, L}$ для заданного помеченного графа $D$ и многокомпонентного контекстно-свободного языка $L$. -\end{definition} - -Другими словами, результатом решения задачи MCFL-достижимости является набор пар вершин, между которыми существует путь, образующий слово из заданного MCFL. - -Далее мы строим алгоритм для решения задачи MCFL-достижимости. - -\section{Матричный алгоритм MCFL-достижимости} -\label{sec:all-path-algo} -В этом разделе мы представляем алгоритм для решения задачи MCFL-достижимости, основанный на матричных операциях. - -\subsection{Алгоритм} - -\begin{definition} - \label{def:sets-end-alter} - Пусть имеется MCFG $G = (\Sigma, N, S, P)$ в нормальной форме. Тогда $\forall p: A \rightarrow f(B,C) \in P$ определим следующее: - \begin{itemize} - \item $end\_B(p) = \{2(i - 1)|$, если $B^i$ является самым левым символом в компоненте правой части правила $p\} \cup \{2(i - 1) + 1 |$, если $B^i$ является самым правым символом в компоненте правой части правила $p\}$, каждое из множеств упорядочено по компонентам нетерминала $A$, а внутри компонент --- слева направо; - \item $end\_C(p)$ определяется аналогично $end\_B(p)$, но со смещением $2dim(B)$, т.е. $end\_C(p)$ будет иметь элементы вида $2(i - 1) + 2dim(B)$ и $2(i - 1) + 1 + 2dim(B)$; - \item $end\_A(p)$ --- упорядоченное множество пар, у которых первый элемент соответсвует самому левом нетерминалу некоторой компоненты в правиле, а второй элемент --- самому правому, т.е. элементами пар являются элементы множеств $end\_B(p)$ и $end\_C(p)$, определённых выше; - \item $(2(i - 1)) \in alter\_B(p)$ или $(2(i - 1) + 1) \in alter\_B(p)$, если $(2(i - 1)) \notin end\_B(p)$ или $(2(i - 1) + 1) \notin end\_B(p)$, $\forall 1 \leq i \leq dim(B)$ соответственно; - \item $alter\_C(p)$ определяется аналогично $alter\_B(p)$, но со смещением $2dim(B)$. - \end{itemize} -\end{definition} - -Примечание: из описания нормальной формы следует, что $|alter\_B(p)| = |alter\_C(p)|$. - -Пусть имеется MCFG $G = (\Sigma, N, S, P)$ в нормальной форме и помеченный граф $D = (V, E, \Sigma)$, где $|V| = n$. Предлагаемый алгоритм представлен на листинге~\ref{lst:algomcfg}. - -На первом этапе алгоритм обрабатывает правила, в правой части которых есть только терминальные символы. Таким образом, алгоритм восстанавливает пути, которые можно получить за одно применение правила. Процедура $update$ представлена на листинге~\ref{lst:algomcfg2}. Она используется для обновления всех необходимых матриц для правил с нетерминалом $B$ в правой части новыми значениями в соответствии с найденными новыми путями. В процедуре обновления подсчитывается индекс с учетом множеств $end\_B(p)$, $end\_C(p)$, $alter\_B(p)$ и $alter\_C(p)$ и добавляется значение $True$ в соответствии с вычисленным индексом. - -\begin{algorithm}[H] - \floatname{algorithm}{Листинг} - \footnotesize - \begin{algorithmic}[1] - \caption{Алгоритм MCFL-достижимости} - \label{lst:algomcfg} - \State{$G = (\Sigma, N, S, P)$ --- MCFG, $D = (V, E, \Sigma)$ --- помеченный граф} - \State{$A_p, B_p, B_p\_new, C_p, C_p\_new$ $\gets$ нулевые булевы матрицы} - - \Procedure{$MCFL\_reachability$}{$G$, $D$} - \For{$p \in P : p = A \rightarrow (a_1, \dots, a_{d(A)})$} - \For{$(l_1, a_1, r_1), \dots, (l_{d(A)}, a_{d(A)}, r_{d(A)}) \in E$} - \State{$index \gets (l_1,r_1,l_2,\dots,r_{d(A)})$} - \State{$update(A, index)$} - \Comment{добавляем информацию о простых правилах} - \EndFor - \EndFor - - \For{$p \in P : p = A \rightarrow f(B,C)$} - \State{$B_p\_new, C_p\_new \gets B_p, C_p$} \Comment{все значения являются новыми на первой итерации} - \EndFor - - \While{матрицы $B_p$, $C_p$ изменяются} - \For{$p \in P : p = A \rightarrow f(B,C)$} \Comment{рассматриваем сложные правила} - \State{$A_p\_new \gets B_p\_new \times C_p + B_p \times C_p\_new$} \Comment{используем только новые значения} - \State{$B_p\_new, C_p\_new \gets$ пустые булевы матрицы} - - \For{$(i,j): A_p\_new[i,j] = True \wedge A_p[i,j] = False$} - \State{$A_p[i,j] \gets True$} - \State{$index \gets transform\_index(ToIndex(i), ToIndex(j), p)$} - \State{$update(A, index)$} - \Comment{добавляем новую информацию для нетерминала $A$} - \EndFor - \EndFor - \EndWhile - \State{$Res \gets$ пустая булева матрица} - \For{$p \in P : p = S \rightarrow f(B,C)$} - \Comment{вычисляем всю необходимую информацию для стартового нетерминала $S$} - \For{$(i,j): S_p[i,j] = True$} - \State{$index \gets transform\_index(ToIndex(i), ToIndex(j), p)$} - \State{$Res[index[0], index[1]] \gets True$} \Comment{размер индекса равен 2, так как $dim(S) = 1$} - \EndFor - \EndFor - \Return $Res$ - \EndProcedure - - - - \end{algorithmic} -\end{algorithm} - -В строке 6 листинга~\ref{lst:algomcfg} найдены $dim(A)$ путей длины 1 или 0, соответствующие компонентам правила $A \rightarrow (a_1, \dots, a_{dim(A)})$. То есть каждая пара $(l_i, r_i)$ --- это пара вершин, между которыми существует путь, порождённый из $i$-ой компоненты правила. Отметим два факта об этом индексе. Во-первых, в этом индексе есть $dim(A)$ пар, то есть количество элементов в нём чётное. Во-вторых, такой индекс можно закодировать как $(n+1)$-арное число ($n$ --- количество вершин в графе $D$). Второй факт позволяет использовать некоторый алгоритм $FromIndex$ (обратный ему $ToIndex$) для перевода такого числа в систему счисления с основанием $(n+1)$. Чётность числа элементов позволяет разделить индекс пополам и записать первую часть в индекс строки матрицы, а вторую --- в индекс столбца. Таким образом, факт о найденном пути для нетерминала запишем в квадратную булеву матрицу, разделив индекс пополам и переведя каждую часть в нужную систему счисления (пусть это будут числа $i$ и $j$), а в ячейку $(i, j)$ поместим значение $True$. - - -\begin{algorithm}[H] - \floatname{algorithm}{Листинг} - \footnotesize - \begin{algorithmic}[1] - \caption{Процедура обновления матриц} - \label{lst:algomcfg2} - - \Procedure{$update$}{$B$, $index$} - \Comment{обновляет матрицы для всех правил с $B$ в правой части} - \For{$p \in P : p = A \rightarrow f(B,C) $} - \State{$i_B, j_B \gets$ пустые списки} - \For{$end \in end\_B(p)$} - \State{$i_B.append(index[end])$} - \EndFor - - \For{$alter \in alter\_B(p)$} - \State{$j_B.append(index[alter])$} - \EndFor - \State{$B_p[FromIndex(i_B), FromIndex(j_B)] \gets True$} - \EndFor - - \For{$p: A\rightarrow f(C,B) $} - \State{$i_B, j_B \gets$ пустые списки} - \For{$alter \in alter\_B(p)$} - \State{$i_B.append(index[alter - 2d(C)])$} - \EndFor - - \For{$end \in end\_B(p)$} - \State{$j_B.append(index[end - 2d(C)])$} - \EndFor - \State{$B_p[FromIndex(i_B), FromIndex(j_B)] \gets True$} - \EndFor - \EndProcedure - - \end{algorithmic} -\end{algorithm} - -Далее, для каждого правила с нетерминалами в правой части алгоритм использует пять матриц. А именно, для правила $p$ вида $A \rightarrow f(B, C)$ алгоритм поддерживает матрицу $B_p$, в которой хранится результат, учитывающий множества из определения~\ref{def:sets-end-alter} для нетерминала $B$, а также матрицу $B_p\_new$, в которой хранится результат, учитывающий множества, полученные только на предыдущем шаге. Аналогично для нетерминала $C$. Также информация о найденных путях, соответствующих данному правилу, хранится в матрице $A_p$ с учетом множества $end\_A(p)$. А после обработки правил с терминальными символами в правой части необходимо добавить новые результаты в поддерживаемые матрицы. Именно это и делает алгоритм в строках 8-9. - -Далее, в строке 12 алгоритм вычисляет новые пути в графе, используя четыре матрицы для нетерминалов из правой части правил. При этом алгоритм обновляет матрицы $B_p\_new$ и $C_p\_new$ для хранения только тех новых значений, которые были добавлены на данной итерации. Также алгоритм записывает только новые значения в матрицу $A_p$ для нетерминала $A$ и распространяет новые результаты среди всех матриц для нетерминала $A$ в правых частях других правил. - -Алгоритм продолжает работу, используя цикл в строках 10-17, пока на текущей итерации появилось хотя бы одно новое значение. На последнем шаге алгоритм собирает значения из всех правил, где в левой части есть стартовый нетерминал, и заносит их в матрицу $Res$ для получения результата MCFL-достижимости. Индексы должны быть пересчитаны с помощью процедуры $transform\_index$, представленной на листинге~\ref{lst:algomcfg3}. - -\begin{algorithm}[H] - \floatname{algorithm}{Листинг} - \footnotesize - \begin{algorithmic}[1] - \caption{Процедура для преобразования индекса} - \label{lst:algomcfg3} - - \Procedure{$transform\_index$}{$i$, $j$, $p$} - \Comment{преобразует индексы $i$ и $j$ в соответствии с множеством $end\_A(p)$} - \State{$A \gets $ нетерминал из левой части правила $p$} - \State{$index \gets$ пустой список} - \For{$(end_l, end_r) \in end\_A(p)$} - \If{$end_l < 2d(B)$} - \State{$pos \gets$ позиция $end_l$ в $end\_B(p)$} \State{$index.append(i[pos])$} - \Else - \State{$pos \gets$ позиция $end_l$ в $end\_C(p)$} \State{$index.append(j[pos])$} - \EndIf - - \If{$end_r < 2d(B)$} - \State{$pos \gets$ позиция $end_r$ в $end\_B(p)$} \State{$index.append(i[pos])$} - \Else - \State{$pos \gets$ позиция $end_r$ в $end\_C(p)$} \State{$index.append(j[pos])$} - \EndIf - \EndFor - \Return $index$ - \EndProcedure - - \end{algorithmic} -\end{algorithm} - -Матрица $Res$, полученная в результате работы алгоритма, представленного на листинге~\ref{lst:algomcfg}, является ответом на задачу $MCFL$-достижимости. - - -% Consider a $2m$ - dimensional matrix $Res$ for $A \in N$ of size $(n + 1)^{2m}$ ($2m$ is Cartesian product degree). For convenience of notation, we assume that $Res[l_1, r_1, l_2, r_2, \dots, l_{d(A)}, r_{d(A)}, 0, \dots, 0] = Res[l_1, r_1, l_2, r_2, \dots, l_{d(A)}, r_{d(A)}]$. - -% Denote matrix $Res$ for $A \in N$ like $Res_A$. - -% Boolean matrix $Res_A$ indexing can be conveniently represented as $(l_1, r_1,$ $\dots, l_{d(A)}, r_{d(A)})$. This representation denote $(n+1)-ary$ number, what can be useful in the implementation. We call \emph{FromIndex} the algorithm obtaining a number from an index for matrix $Res_A$ and \emph{ToIndex} inverse to it. Matrix $Res_A$ can be represented as a square matrix of size $FromIndex((n+1, \dots, n+1)) \times FromIndex((n+1, \dots, n+1))$ ($|(n+1, \dots, n+1)|$ = $2m$), since each index of the matrix $Res_A$ has an even number of elements. That is, we can halve the index and store the left side in the row index, and the right side in the column index. If necessary, we can get the full index by concatenating the results of \emph{ToIndex}. - -% We construct the algorithm in such a way that it is true that $\forall i: 1 \leq i \leq d(A) \ \ \exists \pi_i$ --- path between $l_i$ and $r_i: A \xLongrightarrow[G]{*} (l(\pi_1), \dots, \pi_{d(A)})$ iff $Res[l_1, r_1, \dots, l_{d(A)}, r_{d(A)}] = True$. We call it \emph{main condition} of the algorithm. - -% The algorithm consists of two main steps. The first step is to process the terminating rules of $G$. For this consider $p: A \rightarrow (a_1, \dots, a_{d(A)}) \in P$. To satisfy the main condition, set $Res[l_1, r_1, \dots$ $, l_{d(A)}, r_{d(A)}] = True$ iff $(l_1, a_1, r_1), \dots, (l_{d(A)}, a_{d(A)} r_{d(A)}) \in E$ (all combinations). - -% The second step is to consider non-terminating rules. For this consider $p: A \rightarrow f(B,C) \in P$. - -% Construct two boolean matrices $B_p$ and $C_p$ from $Res_B$, $end\_B(p)$, $alter\_B(p)$, $Res_C$, $end\_C(p)$ and $alter\_C(p)$. - -% Describe construction $B_p$. Consider $\forall i_{res} = (l_1, r_1, \dots, l_{d(B)}, r_{d(B)}): Res_B[l_1, r_1, \dots, l_{d(B)}, r_{d(B)}] = True$ and construct index by taking the elements of $i_{res}$ at the positions pointed by the the elements $end\_B(p)$ and putting them in the order of consideration of the elements $end\_B(p)$. Denote the resulting index $i_B$. Similarly, we construct $j_B$ using $alter\_B(p)$. At the end we put $B_p[FromIndex(i_B)$ $, FromIndex(j_B)] = True$. - -% Similarly, we construct $C_p$ but in the process of construction consider the values of $end\_C(p)$ and $alter\_C(p)$ reduced by $2d(B)$. We cannot store the values from these sets immediately equal to the positions for the index, since it is necessary to distinguish them from the value from the sets $end\_B(p)$, $alter\_B(p)$. - -% Further, we calculate $A_p = B_p \times C_p$. - -% At the end, update the Boolean matrix $Res_A$ using $A_p$. To do this, consider $\forall (i,j): A_p[i,j] = True$, compute $i_A = ToIndex(i)$ and $j_A = ToIndex(j)$. We get the index for the matrix $Res_A$ by putting the elements $i_A$ and $j_A$ in the right positions using ordered pairs from $end\_A$. - - -\subsection{Пример} - -Рассмотрим некоторые шаги алгоритма на примере. В качестве входных данных возьмем граф $D_1$, представленный на рисунке~\ref{fig:example_input_graph_mcfg}, и многокомпонентную контекстно-свободную грамматику $G'_1$ из раздела~\ref{normalformmcfg}. - -\begin{figure}[h] - \centering - \resizebox{\columnwidth}{!}{\begin{tikzpicture}[shorten >=1pt,auto] - \node[state] (q_0) {$1$}; - \node[state] (q_1) [right=of q_0] {$2$}; - \node[state] (q_2) [right=of q_1] {$3$}; - \node[state] (q_3) [right=of q_2] {$4$}; - \node[state] (q_4) [right=of q_3] {$5$}; - \path[->] - (q_0) edge[bend left,above] node {$a$} (q_1) - (q_1) edge[bend left,above] node {$b$} (q_2) - (q_2) edge[bend left,above] node {$c$} (q_3) - (q_3) edge[bend left,above] node {$d$} (q_4) - (q_4) edge[bend left,below] node {$a$} (q_3) - (q_3) edge[bend left,below] node {$b$} (q_2) - (q_2) edge[bend left,below] node {$c$} (q_1) - (q_1) edge[bend left,below] node {$d$} (q_0); - \end{tikzpicture} - } - \caption{Входной граф $D_1$} - \label{fig:example_input_graph_mcfg} -\end{figure} - -На первом шаге алгоритм обрабатывает простые правила $G_1$ (строки 4-7 в листинге~\ref{lst:algomcfg}). Также алгоритм обновляет матрицы с суффиксом $\_new$ для нетерминалов в правых частях каждого правила. Рассмотрим, например, как выглядят после этих обновлений матрицы $B_p\_new$ и $C_p\_new$ для правила $S^1 \rightarrow S_1^1 S_2^1 S_1^2 S_2^2$. Для этого правила алгоритм использует множества из определения~\ref{def:sets-end-alter}, которые выглядят следующим образом. - -\begin{center} - \begin{itemize} - \item $end\_B = \{0\}$ - \item $alter\_B = \{1,2,3\}$ - \item $end\_C = \{7\}$ - \item $alter\_C = \{4,5,6\}$ - \item $end\_A = \{(0, 7)\}$ - \end{itemize} -\end{center} - -\begin{center} - $B_p = B_p\_new = $ {\footnotesize - \bordermatrix{\text{ }&(2,3,2)&(2,3,4)&(4,3,2)&(4,3,4)\cr - (1)&True&True&.&.\cr - (5)&.&.&True&True} - } -\end{center} - - -\begin{center} - $C_p = C_p\_new = $ $C_p$ = \bordermatrix{\text{ }&(1)&(5)\cr - (2,3,2)&True&.\cr - (4,3,2)&.&True\cr - (2,3,4)&True&.\cr - (4,3,3)&.&True} -\end{center} - - - -% At the first step, the algorithm process the terminal rules of $G_1$ (row 5-8 in listing~\ref{lst:algomcfg}). Finally put $\forall N \in \{A,B,C,D\}, x \in \Sigma: N \rightarrow x \in P,$ $Res_N[i,j] = True$, where $(i, x, j) \in E$ and $\forall N \in \{S_1, S_2\}: (N^1, N^2) \rightarrow (x_1, x_2) \in P,$ $Res_N[i_1,j_1,i_2,j_2] = True$, where $(i_1, x_1, j_1), (i_2, x_2, j_2) \in E$. At the end of this step, the matrix $Res$ looks like this. We present the matrix $Res$ without boolean decomposition for brevity. As noted above, the indexing of the original matrix $Res_N$ for some nonterminal N can be obtained by concatenating the row and column index. For example, if $i=(1,2)$ and $j = (3,4)$ then $index = (1,2,3,4)$. - -% {\footnotesize - % \bordermatrix{\text{ }&(1)&(2)&(3)&(4)&(5)&(2,1)&(3,2)&(3,4)&(4,5)\cr - % (1)&.&\{A\}&.&.&.&.&.&.&.\cr - % (2)&\{D\}&.&\{B\}&.&.&.&.&.&.\cr - % (3)&.&\{C\}&.&\{C\}&.&.&.&.&.\cr - % (4)&.&.&\{B\}&.&\{D\}&.&.&.&.\cr - % (5)&.&.&.&\{A\}&.&.&.&.&.\cr - % (1,2)&.&.&.&.&.&.&\{S_1\}&\{S_1\}&.\cr - % (2,3)&.&.&.&.&.&\{S_2\}&.&.&\{S_2\}\cr - % (4,3)&.&.&.&.&.&\{S_2\}&.&.&\{S_2\}\cr - % (5,4)&.&.&.&.&.&.&\{S_1\}&\{S_1\}&.} - % } - -На втором шаге алгоритм обрабатывает правила с нетерминальными символами (строки 10-17 в листинге~\ref{lst:algomcfg}). Рассмотрим правило с нетерминалом $S$ в левой части. Сначала алгоритм перемножает матрицы $B_p$, $B_p\_new$, $C_p$ и $C_p\_new$ в указанном порядке (строка 12 в листинге~\ref{lst:algomcfg}). В результате вычисляется матрица $A_p\_{new}$ следующего вида. Обратите внимание, что строки и столбцы с нулевыми значениями мы опускаем. - -\begin{center} - $A_p\_new$ = \bordermatrix{\text{ }&(1)&(5)\cr - (1)&True&True\cr - (5)&True&True} -\end{center} - -Далее алгоритм попытается распространить информацию о найденных путях и рассмотреть другие правила. Однако далее никаких других путей получено не будет. На последнем этапе алгоритм строит матрицу для стартового нетерминала, которая в данном случае будет совпадать с предыдущей матрицей. - -\begin{center} - $Res = A_p$ = \bordermatrix{\text{ }&(1)&(5)\cr - (1)&True&True\cr - (5)&True&True} -\end{center} - -Таким образом, алгоритм получил информацию о том, что существуют пути, удовлетворяющие грамматике $G_1$, из вершины 1 в 5, из 5 в 1, из 1 в 1 и из 5 в 5. Поэтому многокомпонентное контекстно-свободное отношение $R_{D_1, L(G_1)} = \{(1, 5), (5, 1), (1, 1), (5, 5)\}$. - -% First, the algorithm builds the matrix $B_p$ and $C_p$ (row 8-27 in listing~\ref{lst:algomcfg}, using the procedure $build\_B_pC_p$). For example, considering $i=(1,2)$ and $j=(3,4)$, where $Res_{S_1}[i,j] = True$, in this case initializes $B_p[(1), (2,3,4)] = True$, since $end\_B = \{0\}$ and $alter\_B = \{1,2,3\}$, that is, using the indexing of the original matrix $Res_{S_1}$ $index = (1,2,3,4)$, the first set dictates what needs to be chosen $(1)$ as the index row of the matrix $B_p$ (since $(1)$ is at position 0 in $index$). The second set dictates what needs to be chosen $(2,3,4)$ as the index column for the same reasons. - -% $B_p$ = \bordermatrix{\text{ }&(2,3,2)&(4,3,2)&(2,3,4)&(4,3,3)\cr - % (1)&True&.&True&.\cr - % (5)&.&True&.&True} - -% $C_p$ = \bordermatrix{\text{ }&(1)&(5)\cr - % (2,3,2)&True&.\cr - % (4,3,2)&.&True\cr - % (2,3,4)&True&.\cr - % (4,3,3)&.&True} - -% Second, the algorithm multiply $B_p$ and $C_p$. - -% $A_p = B_p \times C_p$ = \bordermatrix{\text{ }&(1)&(5)\cr - % (1)&True&True\cr - % (5)&True&True} - -% At the end of the iteration, the matrix $Res_S$ is updated (row 41-59 in listing~\ref{lst:algomcfg}). At this step, it is known that $i$ is obtained using the set $end\_B$ and j using the set $end\_C$, where $A_p[i,j]=True$. The algorithm consider $(end_l, end_r) = (0,7)$. Since $end_l < 2d(B) = 4$ it takes the position of $end_l$ in $end\_B$ ($end\_B$ is ordered set) and puts in $index$ the value at that position (in this case $pos = 0$) in $i_A$ (which was received in the row 42). Similarly for $end_r$. - -% $Res_S =$ \bordermatrix{\text{ }&(1)&(5)\cr - % (1)&True&True\cr - % (5)&True&True} - -\subsection{Корректность и сложность} -Аналогично доказательству корректности матричного алгоритма КС-достижимости, можно показать, что следующая теорема справедлива по индукции на высоты деревьев вывода строк, образованных найденными путями в графе. - -\begin{theorem}\label{thm:correctness} - Пусть даны MCFG $G = (\Sigma, N, S, P)$ в нормальной форме и помеченный граф $D =(V, E, \Sigma)$. Пусть $Res$ --- матрица, полученная в результате работы алгоритма (листинг~\ref{lst:algomcfg}). Тогда $(v_0, v_n) \in R_{D,L(G)}$ тогда и только тогда, когда $Res[v_0,v_n] = True$. -\end{theorem} - -Наиболее трудоёмкой частью алгоритма является вычисление новых значений операцией $B_p \times C_p$ в строке 13. Далее мы оценим время, необходимое для вычисления $B_p \times C_p$. Предположим, что размеры булевых матриц $B_p$ и $C_p$ равны $(n+1)^q \times (n+1)^r$ и $(n+1)^r \times (n+1)^s$, соответственно. Тогда для каждого правила $p: A \rightarrow f(B,C)$ мы определяем \textit{степень} этого правила $e(p) = dim(A) + dim(B) + dim(C)$. Также определим \textit{multiplication unit} правила $p$ следующим образом. - -\begin{definition} - Пусть дана MCFG $G = (\Sigma, N, S, P)$ в нормальной форме. Тогда для каждого правила $p: A \rightarrow f(B,C)$ оперделим число $i(p)$, называемое \textit{multiplication unit} правила p, как $dim(A) + dim(B) + dim(C) - 2 \cdot max\{dim(A), dim(B), dim(C)\}$. -\end{definition} - -%According to~\cite{nakanishi1997efficient}, the $B_p \times C_p$ operations can be computed in $O(n^{e(p) - 0.624i(p)})$. Now we must estimate the number of iterations of the algorithm in listing~\ref{lst:algomcfg}. In~\cite{nakanishi1997efficient} the algorithm solves the MCFL recognition problem, and only $n$ iterations are needed. Thus, the MCFL recognition algorithm in~\cite{nakanishi1997efficient} computes the result in time $O(n^{e(p) - 0.624i(p) + 1})$. In our MCFL-reachability algorithm, we may need to make more iterations. The matrices $B_p$ (or $C_p$) can only change if a new tuple of paths $(\pi_1, \ldots, \pi_{d(B)})$ was found, such that $B \xLongrightarrow[G]{*} (l(\pi_1), \dots, l(\pi_{d(B)}))$. Such tuples of paths are described in the algorithm using the indices $(l_1, r_1, l_2, \ldots, r_{d(B)})$ where $\forall 1 \leq i \leq d(B)$, $\pi_i$ --- is a path from vertex $l_i$ to vertex $r_i$. In the worst case, exactly one new index will appear on each iteration. Thus, the number of iterations does not exceed the number of distinct indices. Let $m$ be the dimension of the MCFG $G$. Then the number of distinct indices is $O(n^{2m})$. Therefore, the following theorem holds. - -\begin{theorem}\label{thm:complexity} - Пусть дана m-MCFG $G = (\Sigma, N, S, P)$ в нормальной форме и помеченный граф $D =(V, E, \Sigma)$. Пусть $p'$ --- правило грамматики, для которого $e(p') - 0.624i(p') = max\{e(p) - 0.624i(p) \mid p\in P\}$, и пусть $e' = e(p')$, $i' = i(p')$. Тогда алгоритм, представленный на листинге~\ref{lst:algomcfg}, завершит работу за $O(|V|^{e' - 0.624i' + 2m})$. -\end{theorem} - -Это первое наивное ограничение временной сложности для проблемы MCFL-достижимости. Например, для грамматики $G'_1$ из раздела~\ref{normalformmcfg}, $e' = 5$, $i' = 1$, а $m = 2$. Таким образом, граница временной сложности для этой грамматики составляет $O(|V|^{8,376})$. Однако $O(n^{2m})$ итераций может быть достигнуто только на специальных искусственных графах, а обычно на реальных графах количество итераций невелико. Кроме того, известны приёмы улучшения такой оценки сложности путём рекурсивного умножения подматриц~\cite{Valiant:1975:GCR:1739932.1740048}. Наконец, оценка сложности может быть улучшеноа за счёт учёта разреженности матриц и исползования операций над разреженными матрицами. diff --git a/tex/Multiple_Context-Free_Languages.tex b/tex/Multiple_Context-Free_Languages.tex deleted file mode 100644 index 95002a8..0000000 --- a/tex/Multiple_Context-Free_Languages.tex +++ /dev/null @@ -1,207 +0,0 @@ -\chapter[Многокомпонентные контекстно-свободные языки]{Многокомпонентные контекстно-свободные языки\footnote{Мы дадим лишь базовые определения и приведём краткий обзор данного класса. В качестве отправной точки для более детального изучения можно порекомендовать материалы, подготовдленные Сильваном Салвати (Sylvain Salvati): \url{https://www.labri.fr/perso/salvati/downloads/cours/esslli/}}} - -\textit{Многокомпонентны контекстно-свободные языки} (и соответствующий класс грамматик) --- это строгое расширение контекстно-свободных языков (грамматик), обладающее рядом свойств !!! - -\begin{definition} - \textit{m-MCFG(r)} это четвёрка $\langle \Sigma, N, S, P \rangle$ - \begin{itemize} - \item $\Sigma$ --- терминальный алфавит - \item $N$ --- нетерминальные символы. Максимальный ранг (арность, местность) равен $m$. - \item $S$ --- стартовый нетерминальный символ ранга 1 - \item $P$ --- множество правил вида - $$ - A(s_1,\ldots,s_k) \leftarrow B_1(x_1^1,\ldots,x_{k_1}^1), \ldots, B_n(x_1^n,\ldots,x_{k_n}^n) - $$ - \begin{itemize} - \item $A$ --- нетерминал ранга $k$, $B_i$ --- нетерминалы ранга $k_i$, $n \leq r$ - \item Все $x^i_j$ попарно различны (переменные) - \item $s_i \in (\Sigma \cup X)^*, X = \bigcup_{i=1}^n \bigcup_{j=1}^{k_i} {x^i_j}$ - \end{itemize} - \end{itemize} - \end{definition} - -Приведём примеры многокомпонентных контекстно-свободных грамматик. Для начал рассмотрим грамматики для известных нам контекстно-свободных языков: -\begin{itemize} - \item язык вложенных скобок (\ref{grm:nestedbrs_cfg} и \ref{grm:nestedbrs_mcfg}, соответственно);\\ - \begin{minipage}[t]{0.4\textwidth} - \begin{align}\label{grm:nestedbrs_cfg} - S &\to a S b \nonumber \\ - S &\to \varepsilon - \end{align} - \end{minipage} - ~ - \begin{minipage}[t]{0.2\textwidth} - \end{minipage} - ~ - \begin{minipage}[t]{0.4\textwidth} - \begin{align}\label{grm:nestedbrs_mcfg} - S(axb) & \leftarrow S(x) \nonumber \\ - S(\varepsilon) & \leftarrow - \end{align} - \end{minipage} - \item язык Дика на одном типе скобок(\ref{grm:d1_cfg} и \ref{grm:d1_mcfg}, соответственно).\\ - \begin{minipage}[t]{0.4\textwidth} - \begin{align}\label{grm:d1_cfg} - S &\to a S b S \nonumber \\ - S &\to \varepsilon - \end{align} - \end{minipage} - ~ - \begin{minipage}[t]{0.2\textwidth} - \end{minipage} - ~ - \begin{minipage}[t]{0.4\textwidth} - \begin{align}\label{grm:d1_mcfg} - S(ax_1bx_2) & \leftarrow S(x_1), S(x_2) \nonumber \\ - S(\varepsilon) & \leftarrow - \end{align} - \end{minipage} - -\end{itemize} - -Теперь рассмотрим грамматику для языка $L = \{a^nc^mb^nd^m \mid n \in \mathbb{N}, m \in \mathbb{N} \}$, не являющегося контекстно-свободным: - \begin{align*} - S(x_1 y_1 x_2 y_2) & \leftarrow P(x1,x2),Q(y_1,y_2) \\ - P(ax_1, bx_2) & \leftarrow P(x_1,x_2) \\ - P(\varepsilon,\varepsilon) &\leftarrow \\ - Q(cx_1, dx_2) & \leftarrow Q(x_1,x_2) \\ - Q(\varepsilon,\varepsilon) &\leftarrow - \end{align*} - - - - - - Расширения MCFG - \begin{enumerate} - \item \textbf{PMCFG} (parallel MCFG) - $$ - A(x, ax) \leftarrow B(x) - $$ - - \item - $$ - A(x) \leftarrow B(x),C(x) - $$ - \item \textbf{simpleLMG} - $$ - A(x, x) \leftarrow B(x),C(x) - $$ - \end{enumerate} - - $MCFL \varsubsetneq PMCFL \varsubsetneq simpleLMG = P$ - - $\{a^{2^n} \mid n\geq 0\} \in PMCFL - MCFL $ - - $S(xx) \leftarrow S(x)$ - - $S(a) \leftarrow $ - - Разновидности MCFG - \begin{itemize} - \item \textbf{Неудаляющая} --- $\forall i \in \{i,\ldots,n\}, j\in \{1,\ldots,k_i\} \ x^i_j \text{ используется в } s_1,\ldots,s_k $ - \item \textbf{Непереставляющая} --- $\forall i \in \{i,\ldots,n\}, j,k\in \{1,\ldots,k_i\}, \text{если} j < k, \text{ то } x^i_j \text{ встречается в } s_1,\ldots,s_k \text{ перед } x^i_k$ - \item \textbf{Well-nested} --- неудаляющая, непереставляющая и - \begin{align*} - &\forall i,i' \in \{i,\ldots,n\}, i\neq i', \\ - &j\in \{1,\ldots,k_i-1\}, j\in \{1,\ldots,k_{i'}-1\},\\ - &s_1\cdots s_k \notin (\Sigma \cup X)^* x^i_j (\Sigma \cup X)^* x^{i'}_{j'} (\Sigma \cup X)^* x^i_{j+1} (\Sigma \cup X)^* x^{i'}_{j'+1}(\Sigma \cup X)^* - \end{align*} - \end{itemize} - - Пример well-nested MCFG - \begin{itemize} - %\item[\faCheck] [\faTimes] - \item[\faCheck] $A(\highlight[pink]{x_1},\highlight{z_1,z_2},\highlight[pink]{x_2},\highlight[green]{y_1,y_2,y_3},\highlight[pink]{x_3}) \leftarrow B(x_1,x_2,x_3),C(y_1,y_2,y_3),D(z_1,z_2)$ - \item[\faTimes] $A(\highlight{z_1},\highlight[pink]{x_1},\highlight[green]{y_1},\highlight[pink]{x_2},\highlight{z_2},\highlight[green]{y_2},\highlight[pink]{x_3},\highlight[green]{y_3}) \leftarrow B(x_1,x_2,x_3),C(y_1,y_2,y_3),D(z_1,z_2)$ - \end{itemize} - - \begin{theorem}[genaral MCFG] - \begin{align*} - &\forall L \in \text{m-MCFG } \exists n \geq 1 \ \underline{\boldsymbol{\exists} z} \in L (|z| \geq n) \\ - &\exists \text{ разбиение } z=u_1 v_1 w_1 s_1 u_2 \ldots u_m v_m w_m s_m u_{m+1}, \Sigma|v_js_j| \geq 1 \\ - &\forall i \geq 0: z_i = u_1 v_1^i w_1 s_1^i u_2 \ldots u_m v_m^i w_m s_m^i u_{m+1} \in L - \end{align*} - \end{theorem} - - \begin{theorem}[well-nested MCFG] - \begin{align*} - &\forall L \in \text{m-wnMCFG } \exists n \geq 1 \ \underline{\boldsymbol{\forall} z} \in L (|z| \geq n) \\ - &\exists \text{ разбиение } z=u_1 v_1 w_1 s_1 u_2 \ldots u_m v_m w_m s_m u_{m+1}, \Sigma|v_js_j| \geq 1 \\ - &\forall i \geq 0: z_i = u_1 v_1^i w_1 s_1^i u_2 \ldots u_m v_m^i w_m s_m^i u_{m+1} \in L - \end{align*} - \end{theorem} - - Иерархии внутри MCFL - \begin{theorem} - $(m*(k-1))$-$MCFL(r-k) \subseteq m$-$MCFL(r) $ если $1 \leq k \leq r - 2$ - \end{theorem} - - \begin{theorem}[Seki et al] - $L_{m+1} = \{a_1^nb_1^n\cdots a_{m+1}^n b_{m+1}^n \mid n\in \mathbb{N}\}$ является $(m+1)$-$MCFL(1)$, но не является $m$-$MCFL(r)$ ни для какого $r$ - \end{theorem} - - -\begin{figure} - \includegraphics[width=\textwidth]{figures/mcfg/mcfg.pdf} - \label{fig:mcfg_hierarachy_1} - \caption{Иерархия по $m$} -\end{figure} - - Иерархия для $m=1$ - \begin{theorem} - 1-MCFL = CFL - \end{theorem} - - \begin{theorem} - 1-MCFL(1) $\varsubsetneq$ 1-MCFL(2) - \end{theorem} - - \begin{theorem} - 1-MCFL($r$) = 1-MCFL($r+1$), $r\geq2$ - \end{theorem} - - Иерархия для $m=2$ - \begin{theorem}[Ramow, Satta] - 2-MCFL(2) = 2-MCFL(3) - \end{theorem} - - \begin{theorem} - Если $m>2$ или $r>2$, то m-MCFL(r) $\varsubsetneq$ m-MCFL(r+1) - \end{theorem} - -\begin{figure} - \includegraphics[width=\textwidth]{figures/mcfg/mcfg_2.pdf} - \label{fig:mcfg_hierarachy_2} - \caption{Иерархия по $r$} -\end{figure} - - -Про MIX и $O_n$ - -\begin{itemize} - \item $mix = \{\omega \in \{a,b\}^* \mid |\omega|_a = |\omega|_b \}$ --- контекстно-свободный язык - - \item $MIX = \{\omega \in \{a,b,c\}^* \mid |\omega|_a = |\omega|_b = |\omega|_c\}$ --- MCFL? Хотелось верить, что нет - \begin{itemize} - \item \href{https://hal.inria.fr/inria-00564552/document}{MIX is a 2-MCFL and the word problem in $\mathbb{Z}^2$ is solved by a third-order collapsible pushdown automaton, Sylvain Salvati, 2011}~\cite{salvati:inria-00564552} - \end{itemize} - \item $O_2=\{\omega \in \{a,\overline{a},b,\overline{b}\}^* \mid |\omega|_a=|\omega|_{\overline{a}} \wedge |w|_b=|w|_{\overline{b}}\}$ - \item $O_n=\{\omega \in \{a_1,\overline{a_1},a_2,\overline{a_2},\ldots,a_n,\overline{a_n}\}^* \mid |\omega|_{a_1}=|\omega|_{\overline{a_1}} \wedge |w|_{a_2}=|w|_{\overline{a_2}} \wedge \cdots \wedge |w|_{a_n}=|w|_{\overline{a_n}}\}$ - \item $MIX_n = \{\omega \in \{a_1,\ldots,a_n\}^* \mid |\omega|_{a_1} = |\omega|_{a_2} =\cdots = |\omega|_{a_n}\}$ - \item $MIX_n$ регулярно эквивалентен $O_n$ (существует алгоритм построения грамматики одного языка по грамматике другого) - \begin{itemize} - \item \href{https://hal.archives-ouvertes.fr/hal-01771670/document}{$O_n$ is an n-MCFL, Sylvain Salvati, 2018}~\cite{GEBHARDT202241} - \end{itemize} - \end{itemize} - - - \begin{itemize} - \item Варианты леммы о накачке - \item Представимость конкретных языков - \begin{itemize} - \item Многомерный язык Дика: \href{https://link.springer.com/chapter/10.1007/978-3-662-59620-3_5}{Towards a 2-Multiple Context-Free Grammar for the 3-Dimensional Dyck Language, Konstantinos Kogkalidis, Orestis Melkonian, 2019}~\cite{10.1007/978-3-662-59620-3_5} - \item Шафл языков Дика: \href{https://dl.acm.org/doi/10.1145/3093333.3009848}{Context-sensitive data-dependence analysis via linear conjunctive language reachability, Qirun Zhang, Zhendong Su et al, 2017}~\cite{10.1145/3009837.3009848} - \end{itemize} - \end{itemize} - diff --git a/tex/Project.tex b/tex/Project.tex deleted file mode 100644 index e69de29..0000000 diff --git a/tex/RPQ.tex b/tex/RPQ.tex deleted file mode 100644 index 7eb1ed1..0000000 --- a/tex/RPQ.tex +++ /dev/null @@ -1,669 +0,0 @@ -\chapter{Поиск путей с регулярными ограничениями} - -\section{Достижимость между всеми парами вершин} - -Через тензорное произведение. - -Классическое построение пересечения автоматов строит их тензорное произведение. - -Так как мы хотим отвечать ещё и на вопрос о достижимости, что нам надо ещё и транзитивное замыкание посчитать. - -\section{Достижимость с несколькими источниками} - -Достижимость от нескольких стартовых вершин через обход в ширину, основанный на линейной алгебре~\cite{9286186}. - -Идея алгоритма основана на одновременном обходе в ширину графа и конечного автомата, построенного по грамматике. - -В классической версии обхода в ширину, основанного на линейной алгебре, используется вектор, куда записывается фронт обхода графа. -Так, один раз перемножая этот вектор на матрицу смежности графа, можно совершать один шаг в обходе графа. -Покажем на примере, как данный метод может быть использован, когда мы накладываем дополнительные ограничения в виде регулярного языка на путь в графе. - -Для этого, во-первых, предъявим булевые представления для матриц смежности графа и автомата для регулярного языка. Затем, введем специальную блочно--диагональную матрицу -для синхронизации обхода в ширину по двум матрицам смежности. Далее, попробуем наивно реализовать обход в ширину, и посмотрим, почему наивная реализация -может выдавать некорректный результат. -После этого перейдем к реализации обхода в ширину более продвинутым методом, который решает проблему наивного подхода. - -\begin{example} - Возьмём следующий граф. - \begin{center} - \label{input_rpq} - \begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] - \node[state] (q_0) {$1$}; - \node[state] (q_1) [above=of q_0] {$2$}; - \node[state] (q_2) [right=of $(q_0)!0.5!(q_1)$] {$0$}; - \node[state] (q_3) [right=of q_2] {$3$}; - \path[->] - (q_0) edge node {b} (q_1) - (q_1) edge node[pos=0.3] {a} (q_2) - (q_2) edge node[pos=0.7] {a} (q_0) - (q_2) edge[bend left] node[above] {b} (q_3) - (q_3) edge[bend left] node {b} (q_2); - \end{tikzpicture} -\end{center} - -Его матрица смежности имеет следующий вид. -\[ G_1 = -\begin{pmatrix} -. & \{a\} & . & \{b\} \\ -. & . & \{b\} & . \\ -\{a\} & . & . & . \\ -\{b\} & . & . & . -\end{pmatrix} -\] - -Её булева декомпозиция по каждому символу выглядит следующим образом. -\begin{alignat*}{7} -& &&G_{0\_a} &&= \begin{pmatrix} -0 & 1 & 0 & 0 \\ -0 & 0 & 0 & 0 \\ -1 & 0 & 0 & 0 \\ -0 & 0 & 0 & 0 \\ -\end{pmatrix} \ \ \ \ &&G_{0\_b} &&= \begin{pmatrix} -0 & 0 & 0 & 1 \\ -0 & 0 & 1 & 0 \\ -0 & 0 & 0 & 0 \\ -1 & 0 & 0 & 0 \\ -\end{pmatrix} -\end{alignat*} - -Зададим ограничения с помощью регулярного выражения $b^*ab$, которое представляется автоматом из трех последовательных состояний. - -\begin{center} - \begin{tikzpicture}[shorten >=1pt,on grid,auto] - \node[state, initial] (q_0) at (0,0) {$0$}; - \node[state] (q_1) at (2,0) {$1$}; - \node[state, accepting] (q_2) at (4,0) {$2$}; - \path[->] - (q_0) edge node {$a$} (q_1) - (q_1) edge node {$b$} (q_2); - \draw (q_0) edge[loop above] node {$b$} (q_0); - \end{tikzpicture} -\end{center} - - -Автомат может быть задан матрицей смежности (с дополнительной информацией о стартовых и финальных состояниях). - -Для регулярного выражения $b^*ab$ матрица смежности выглядит следующим образом (при этом нужно запомнить, что -состояние $0$ является начальным, $2$ --- конечным). - -\[ G_2 = -\begin{pmatrix} -\{b\} & \{a\} & . \\ -. & . & \{b\} \\ -. & . & . -\end{pmatrix} -\] - -Нам будет необходима булева декомпозиция этой матрицы, и она выглядит следующим образом. - -\begin{alignat*}{7} - & &&R_{0\_a} &&= \begin{pmatrix} - 0 & 1 & 0 \\ - 0 & 0 & 0 \\ - 0 & 0 & 0 - \end{pmatrix} \ \ \ \ &&R_{0\_b} &&= \begin{pmatrix} - 1 & 0 & 0 \\ - 0 & 0 & 1 \\ - 0 & 0 & 0 - \end{pmatrix} -\end{alignat*} - -Для синхронизации обхода составим набор блочно--диагональных матриц, каждая из которых --- это прямая сумма двух матриц: -$D_{0\_a} = R_{0\_a} \oplus G_{0\_a}$ и $D_{0\_a} = R_{0\_b} \oplus G_{0\_b}$. - -\begin{alignat*}{7} - & &&D_{0\_a} &&= - \left(\begin{array}{c c c | c c c c} - 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - \hline - 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 - \end{array}\right) - \ \ \ \ &&D_{0\_b} &&= - \left(\begin{array}{c c c | c c c c} - 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - \hline - 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ - 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 - \end{array}\right) -\end{alignat*} - -Пусть мы решаем частный случай задачи достижимости с несколькими стартовыми вершинами (multiple--source) ---- достижимость с одной стартовой вершиной (single--source). - -Пусть единственной начальной вершиной в графе будет вершина $0$. - -Теперь создадим вектор $v = $ $\fbox{1 0 0} \fbox{1 0 0 0}$, где в первой части стоит единица на месте начального состояния $0$ в автомате. -Во второй части содержится фронт обхода графа, на первом шаге это всегда множество стартовых вершин. В данном случае единица стоит на месте -единственной стартовой вершины --- $0$. - -Совершим один шаг в обходе графа и получим новый фронт обхода графа. -\begin{alignat*}{7} - a:\,\, - & \begin{matrix} - \fbox{1 0 0} \fbox{1 0 0 0} - \end{matrix} && - \times - \left(\begin{array}{c c c | c c c c} - 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - \hline - 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 - \end{array}\right) - &&= \begin{matrix} - \fbox{0 1 0} \fbox{0 1 0 0} - \end{matrix} -\end{alignat*} - -\begin{alignat*}{7} - b:\,\, - & \begin{matrix} - \fbox{1 0 0} \fbox{1 0 0 0} - \end{matrix} && - \times - \left(\begin{array}{c c c | c c c c} - 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - \hline - 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ - 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 - \end{array}\right) - &&= \begin{matrix} - \fbox{1 0 0} \fbox{0 0 0 1} - \end{matrix} -\end{alignat*} - -Сложим два полученных вектора, чтобы получить новый фронт обхода графа: $\fbox{0 1 0} \fbox{0 1 0 0}$ + $\fbox{1 0 0} \fbox{0 0 0 1} = \fbox{1 1 0} \fbox{0 1 0 1}$. - -То есть в наш фронт \fbox{0 1 0 1} попали вершины 1 и 3 соотвественно. А именно, мы совершили следующие переходы в графе и автомате. - -\begin{alignat*}{7} - \begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] - \node[state, red] (q_0) {$1$}; - \node[state] (q_1) [above=of q_0] {$2$}; - \node[state] (q_2) [right=of $(q_0)!0.5!(q_1)$] {$0$}; - \node[state, red] (q_3) [right=of q_2] {$3$}; - \path[->, red] - (q_2) edge node[pos=0.7] {a} (q_0) - (q_2) edge[bend left] node[above] {b} (q_3); - \path[->] - (q_0) edge node {b} (q_1) - (q_1) edge node[pos=0.3] {a} (q_2) - (q_3) edge[bend left] node {b} (q_2); - \end{tikzpicture} - &\hspace{20px} - \begin{tikzpicture}[shorten >=1pt,on grid,auto] - \node[state, draw=none] (q_3) at (0,0) {$$}; % empty node for alignment - \node[state, initial, red] (q_0) at (0,1) {$0$}; - \node[state, red] (q_1) at (2,1) {$1$}; - \node[state, accepting] (q_2) at (4,1) {$2$}; - \path[->, red] - (q_0) edge node {$a$} (q_1); - \path[->] - (q_1) edge node {$b$} (q_2); - \draw (q_0) edge[loop above, red] node {$b$} (q_0); - \end{tikzpicture} -\end{alignat*} - -Совершим еще один шаг алгоритма. Теперь вектор $v$, на который мы умножаем матрицы, имеет следующий вид $\fbox{1 1 0} \fbox{0 1 0 1}$. - -\begin{alignat*}{7} - a:\,\, - & \begin{matrix} - \fbox{1 1 0} \fbox{0 1 0 1} - \end{matrix} && - \times - \left(\begin{array}{c c c | c c c c} - 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - \hline - 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 - \end{array}\right) - &&= \begin{matrix} - \fbox{0 1 0} \fbox{0 0 0 0} - \end{matrix} -\end{alignat*} - -\begin{alignat*}{7} - b:\,\, - & \begin{matrix} - \fbox{1 1 0} \fbox{0 1 0 1} - \end{matrix} && - \times - \left(\begin{array}{c c c | c c c c} - 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - \hline - 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ - 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 - \end{array}\right) - &&= \begin{matrix} - \fbox{1 0 1} \fbox{1 0 1 0} - \end{matrix} -\end{alignat*} - -$\fbox{0 1 0} \fbox{0 0 0 0}$ + $\fbox{1 0 1} \fbox{1 0 1 0} = \fbox{1 1 1} \fbox{1 0 1 0}$. -То есть в наш фронт \fbox{1 0 1 0} попали вершины 0 и 2 соотвественно. Мы совершили следующие переходы в графе и автомате. - -\begin{alignat*}{7} - \begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] - \node[state, gray] (q_0) {$1$}; - \node[state, teal] (q_1) [above=of q_0] {$2$}; - \node[state, teal] (q_2) [right=of $(q_0)!0.5!(q_1)$] {$0$}; - \node[state, gray] (q_3) [right=of q_2] {$3$}; - \path[->, gray] - (q_2) edge node[pos=0.7] {a} (q_0) - (q_2) edge[bend left] node[above] {b} (q_3); - \path[->, red] - (q_0) edge node {b} (q_1) - (q_3) edge[bend left] node {b} (q_2); - \path[->] - (q_1) edge node[pos=0.3] {a} (q_2); - \end{tikzpicture} - &\hspace{20px} - \begin{tikzpicture}[shorten >=1pt,on grid,auto] - \node[state, draw=none] (q_3) at (0,0) {$$}; % empty node for alignment - \node[state, initial, red] (q_0) at (0,1) {$0$}; - \node[state, gray] (q_1) at (2,1) {$1$}; - \node[state, accepting, teal] (q_2) at (4,1) {$2$}; - \path[->, gray] - (q_0) edge node {$a$} (q_1); - \path[->, red] - (q_1) edge node {$b$} (q_2); - \draw (q_0) edge[loop above, red] node {$b$} (q_0); - \end{tikzpicture} -\end{alignat*} - -При этом, можно заметить, что мы достигли конечной вершины в автомате. Последний элемент левой части результирующего -вектора $\fbox{1 1 \textcolor{red}{1}} \fbox{1 0 1 0}$ отвечает за состояние 2, которое является конечным. А значит, обход необходимо остановить, и текущие вершины фронта -обхода графа записать в ответ. - -Таким образом, вершины графа 0 и 2 являются ответом. Однако вершина 0 --- лишняя. Регулярное выражение $b^*ab$ не подразумевает, что -вершина 0 в графе может быть достигнута. Она могла бы быть достигнута по пустой строке в случае, если бы регулярное выражение имело вид $b^*$ или -по строке $aba$ в случае, если бы регулярное выражение имело вид $b^*aba$. - -Это произошло, потому что в векторе $v$ должна кодироваться информация о паре --- вершине графа и состоянии автомата. -Достигнув вершины 0, мы оказались в конечном состоянии автомата, которое было получено с помощью другой вершины --- вершины 2. - -Эту проблему можно решить, закодировав информацию о каждой такой паре в несколько векторов $v$, и ограничив левую -часть вектора $v$ таким образом, чтобы в ней всегда была лишь одна единица. - -Тогда мы получим, что вектор $v$ вида $\fbox{1 0 0} \fbox{1 0 1 0}$ будет хранить информацию о парах (0, 0) и (0, 2), -где первый элемент пары --- состояние автомата, а второй --- вершина графа. - -Аналогично, вектор $v$ вида $\fbox{0 1 0} \fbox{0 1 1 0}$ кодирует информацию о парах (1, 1) и (1, 2). -Вектор $v$ вида $\fbox{0 0 1} \fbox{0 0 1 1}$ кодирует информацию о парах (2, 2) и (2, 3). - -Таким образом, мы будем понимать, в каком состоянии автомата мы находимся для каждой из вершин фронта обхода графа. - -Рассмотрим, как это применяется в разработанном алгоритме, который представлен далее. - -Предлагается ``расклеить'' $v$ в матрицу $M$, состоящую из трех векторов, добавив два вектора $\fbox{0 1 0} \fbox{0 0 0 0}$ и $\fbox{0 0 1} \fbox{0 0 0 0}$. -Во второй части этих векторов стоят нули, так как \fbox{0 1 0} и \fbox{0 0 1} кодируют состояния автомата 1 и 2, которые не являются начальными. - -\begin{alignat*}{7} - & &&M &&=\begin{matrix} - \fbox{1 0 0} \fbox{1 0 0 0} \\ - \fbox{0 1 0} \fbox{0 0 0 0} \\ - \fbox{0 0 1} \fbox{0 0 0 0} - \end{matrix} -\end{alignat*} - -И совершать обход тем же самым образом, но сохранив с помощью матрицы $M$ дополнительную информацию о парах (состояние, вершина). - -\begin{alignat*}{7} - a:\,\, - & \begin{matrix} - \fbox{1 0 0} \fbox{1 0 0 0} \\ - \fbox{0 1 0} \fbox{0 0 0 0} \\ - \fbox{0 0 1} \fbox{0 0 0 0} - \end{matrix} && - \times - \left(\begin{array}{c c c | c c c c} - 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - \hline - 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 - \end{array}\right) - &&= \begin{matrix} - \fbox{0 1 0} \fbox{0 1 0 0} \\ - \fbox{0 0 0} \fbox{0 0 0 0} \\ - \fbox{0 0 0} \fbox{0 0 0 0} - \end{matrix} -\end{alignat*} - -\begin{alignat*}{7} - b:\,\, - & \begin{matrix} - \fbox{1 0 0} \fbox{1 0 0 0} \\ - \fbox{0 1 0} \fbox{0 0 0 0} \\ - \fbox{0 0 1} \fbox{0 0 0 0} - \end{matrix} && - \times - \left(\begin{array}{c c c | c c c c} - 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - \hline - 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ - 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 - \end{array}\right) - &&= \begin{matrix} - \fbox{1 0 0} \fbox{0 0 0 1} \\ - \fbox{0 0 1} \fbox{0 0 0 0} \\ - \fbox{0 0 0} \fbox{0 0 0 0} - \end{matrix} -\end{alignat*} - -Для того, чтобы левая часть матрицы $M$ всегда оставалось единичной, нужно трансформировать в ней строчки особым образом. -Для этого нужно складывать только те вектора в правой части матрицы $M$, у которых в левой части единицы стоят на одинаковых позициях. -После чего переставлять строчки в $M$ так, чтобы левая часть матрицы $M$ принимала единичный вид. -Вектора с пустой левой частью нас при этом не интересуют. - -Тогда правая часть матрицы $M$ будет кодировать текущий фронт обхода графа. - -В нашем примере матрица $M$ для следующего шага обхода выглядит следующим образом. - -\begin{alignat*}{7} - & &&M &&=\begin{matrix} - \fbox{1 0 0} \fbox{0 0 0 1} \\ - \fbox{0 1 0} \fbox{0 1 0 0} \\ - \fbox{0 0 1} \fbox{0 0 0 0} - \end{matrix} -\end{alignat*} - -Видно, что во фронт обхода графа попали вершины 1 и 3. В вершину 1 мы попали в состоянии 1, в вершину 3 --- в состоянии 0. - -Совершаются следующие переходы в графе и автомате. - -\begin{alignat*}{7} - \begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] - \node[state, red] (q_0) {$1$}; - \node[state] (q_1) [above=of q_0] {$2$}; - \node[state] (q_2) [right=of $(q_0)!0.5!(q_1)$] {$0$}; - \node[state, red] (q_3) [right=of q_2] {$3$}; - \path[->, red] - (q_2) edge node[pos=0.7] {a} (q_0) - (q_2) edge[bend left] node[above] {b} (q_3); - \path[->] - (q_0) edge node {b} (q_1) - (q_1) edge node[pos=0.3] {a} (q_2) - (q_3) edge[bend left] node {b} (q_2); - \end{tikzpicture} - &\hspace{20px} - \begin{tikzpicture}[shorten >=1pt,on grid,auto] - \node[state, draw=none] (q_3) at (0,0) {$$}; % empty node for alignment - \node[state, initial, red] (q_0) at (0,1) {$0$}; - \node[state, red] (q_1) at (2,1) {$1$}; - \node[state, accepting] (q_2) at (4,1) {$2$}; - \path[->, red] - (q_0) edge node {$a$} (q_1); - \path[->] - (q_1) edge node {$b$} (q_2); - \draw (q_0) edge[loop above, red] node {$b$} (q_0); - \end{tikzpicture} -\end{alignat*} - -Сделаем еще один шаг алгоритма и придем к конечному состоянию в автомате. - -\begin{alignat*}{7} - a:\,\, - & \begin{matrix} - \fbox{1 0 0} \fbox{0 0 0 1} \\ - \fbox{0 1 0} \fbox{0 1 0 0} \\ - \fbox{0 0 1} \fbox{0 0 0 0} - \end{matrix} && - \times - \left(\begin{array}{c c c | c c c c} - 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - \hline - 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 - \end{array}\right) - &&= \begin{matrix} - \fbox{0 1 0} \fbox{0 0 0 0} \\ - \fbox{0 0 0} \fbox{0 0 0 0} \\ - \fbox{0 0 0} \fbox{0 0 0 0} - \end{matrix} -\end{alignat*} - -\begin{alignat*}{7} - b:\,\, - & \begin{matrix} - \fbox{1 0 0} \fbox{0 0 0 1} \\ - \fbox{0 1 0} \fbox{0 1 0 0} \\ - \fbox{0 0 1} \fbox{0 0 0 0} - \end{matrix} && - \times - \left(\begin{array}{c c c | c c c c} - 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - \hline - 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ - 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ - 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ - 0 & 0 & 0 & 1 & 0 & 0 & 0 - \end{array}\right) - &&= \begin{matrix} - \fbox{1 0 0} \fbox{1 0 0 0} \\ - \fbox{0 0 1} \fbox{0 0 1 0} \\ - \fbox{0 0 0} \fbox{0 0 0 0} - \end{matrix} -\end{alignat*} - -\begin{alignat*}{7} - & &&M &&=\begin{matrix} - \fbox{1 0 0} \fbox{1 0 0 0} \\ - \fbox{0 1 0} \fbox{0 0 0 0} \\ - \fbox{0 0 1} \fbox{0 0 1 0} - \end{matrix} -\end{alignat*} - -Видно, что мы достигли вершины 2 графа в конечном состоянии 2 автомата. При этом вершина 0 графа так же достигнута, как и в наивном варианте алгоритма, но -теперь известно, что это происходит в состоянии 0 автомата. - -\begin{alignat*}{7} - \begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] - \node[state, gray] (q_0) {$1$}; - \node[state, teal] (q_1) [above=of q_0] {$2$}; - \node[state, red] (q_2) [right=of $(q_0)!0.5!(q_1)$] {$0$}; - \node[state, gray] (q_3) [right=of q_2] {$3$}; - \path[->, gray] - (q_2) edge node[pos=0.7] {a} (q_0) - (q_2) edge[bend left] node[above] {b} (q_3); - \path[->, red] - (q_0) edge node {b} (q_1) - (q_3) edge[bend left] node {b} (q_2); - \path[->] - (q_1) edge node[pos=0.3] {a} (q_2); - \end{tikzpicture} - &\hspace{20px} - \begin{tikzpicture}[shorten >=1pt,on grid,auto] - \node[state, draw=none] (q_3) at (0,0) {$$}; % empty node for alignment - \node[state, initial, red] (q_0) at (0,1) {$0$}; - \node[state, gray] (q_1) at (2,1) {$1$}; - \node[state, accepting, teal] (q_2) at (4,1) {$2$}; - \path[->, gray] - (q_0) edge node {$a$} (q_1); - \path[->, red] - (q_1) edge node {$b$} (q_2); - \draw (q_0) edge[loop above, red] node {$b$} (q_0); - \end{tikzpicture} -\end{alignat*} - -Таким образом, в ответ попадает вершина 2. -\end{example} - -Перейдем к формальному описанию алгоритма. - - -Алгоритм принимает на вход граф $\mathcal{G}$, детерминированный конечный автомат $\mathcal{R}$, описывающий регулярную грамматику, и множество начальных вершин $V_{src}$ графа. - -Граф $\mathcal{G}$ и автомат $\mathcal{R}$ можно представить в виде булевых матриц смежности. Так, в виде словаря для каждой метки графа заводится булева матрица смежности, на месте $(i, j)$ ячейки которой стоит 1, если $i$ и $j$ вершины графа соединены ребром данной метки. Такая же операция проводится для автомата грамматики $\mathcal{R}$. - -Далее, мы оперируем с двумя словарями, где ключом является символ метки ребра графа или символ алфавита автомата, а значением --- соответствующая им булевая матрица. - -Для каждого символа из пересечения этих множеств строится матрица $\mathfrak{D}$, как прямая сумма булевых матриц. То есть, строится матрица $\mathfrak{D} = Bool_{\mathcal{R}_a} \bigoplus Bool_{\mathcal{G}_a}$, которая определяется как - -\begin{equation} -\mathfrak{D} = - \left[ - \begin{matrix} - Bool_{\mathcal{R}_a} & 0\\ - 0 & Bool_{\mathcal{G}_a} - \end{matrix} - \right] -\end{equation} - -Где $\mathcal{R}_{a}$ и $\mathcal{G}_{a}$ матрицы смежности соответствующих символов автомата грамматики $\mathcal{R}$ и графа $\mathcal{G}$ для символа $a \in A_\mathcal{R} \cap A_\mathcal{G}$, $A_\mathcal{R} \cap A_\mathcal{G}$ --- пересечение алфавитов. Такая конструкция позволяет синхронизировать алгоритм обхода в ширину одновременно для графа и грамматики. - -Далее вводится матрица $M$, хранящая информацию о фронте обхода графа. Она нужна для выделения множества пройденных вершин и не допускает зацикливание алгоритма. -\begin{equation} -M^{k \times (k + n)} = - \left[ - \begin{matrix} - Id_k & Matrix_{k \times n } - \end{matrix} - \right] -\end{equation} - -Где $Id_k$ --- единичная матрица размера $k$, $k$ --- количество вершин в автомате $\mathcal{R}$, $Matrix_{k \times n }$ --- матрица, хранящая в себе маску пройденных вершин в автомате графа, $n$ --- количество вершин в графе $\mathcal{G}$. - -\subsection{Выходные данные} - -На выходе строится множество $\mathcal{P}$ пар вершин $(v, w)$ графа $\mathcal{G}$ таких, что вершина $w$ достижима из множества начальных вершин, при этом $v \in V_{src}$, $w \not\in V_{src}$. Это множество представляется в виде матрицы размера $|V|\times|V|$, где $(i,j)$ ячейка содержит 1, если пара вершин с индексами $(i, j) \in \mathcal{P}$. - -\subsection{Процесс обхода графа} - -Алгоритм обхода заключается в последовательном умножении матрицы $M$ текущего фронта на матрицу $\mathfrak{D}$. В результате чего, находится матрица $M'$ содержащая информацию о вершинах, достижимых на следующем шаге. Далее, с помощью операций перестановки и сложения векторов $M'$ преобразуется к виду матрицы $M$ и присваивается ей. Итерации продолжаются пока $M'$ содержит новые вершины, не содержащиеся в $M$. На листинге~\ref{BFSRPQ1} представлен этот алгоритм. - -\begin{algorithm}[t] - \caption{Алгоритм достижимости в графе с регулярными ограничениями на основе поиска в ширину, выраженный с помощью операций матричного умножения}\label{BFSRPQ1} - \begin{algorithmic}[1] - \Procedure{BFSBasedRPQ}{$\mathcal{R}=\langle Q, \Sigma, P, F, q \rangle,\mathcal{G}=\langle V, E, L \rangle, V_{src}$} - \State $\mathcal{P}\gets~${Матрица смежности графа} - \State $\mathfrak{D}\gets Bool_\mathcal{R} \bigoplus Bool_\mathcal{G}$\Comment{Построение матриц $\mathfrak{D}$} - \State $M\gets CreateMasks(|Q|,|V|)$ \Comment{Построение матрицы $M$} - \State $M'\gets SetStartVerts(M, V_{src})$ \Comment{Заполнение нач. вершин} - - \While{Матрица~$M$~меняется}{} - \State $M\gets M'\langle\neg M\rangle$\Comment{Применение комплементарной маски} - \ForAll{$a\in (\Sigma \cap L)$} - \State $M'\gets M~$any.pair$~\mathfrak{D}$ - \Comment{Матр. умножение в полукольце} - \State $M'\gets TransformRows(M')$\label{TransformRows} - \Comment{Приведение $M'$ к виду $M$} - \EndFor - \State {$Matrix\gets extractRightSubMatrix(M')$} - \State $V\gets Matrix.reduceVector()$ \Comment{Сложение по столбцам} - \For{$k \in 0\dots|V_{src}|-1$} - \State $W\gets\mathcal{P}.getRow(k)$ - \State $\mathcal{P}.setRow(k, V+W)$ - \EndFor - \EndWhile - \State \textbf{return} $\mathcal{P}$ - \EndProcedure - \end{algorithmic} -\end{algorithm} - -В алгоритме~\ref{BFSRPQ1}, в~\ref{TransformRows} строке происходит трансформация строчек в матрице $M'$. Это делается для того, чтобы представить полученную во время обхода матрицу $M'$, содержащую новый фронт, в виде матрицы $M$. Для этого требуется так переставить строчки $M'$, чтобы она содержала корректные по своему определению значения. То есть, имела единицы на главной диагонали, а все остальные значения в первых $k$ столбцах были нулями. Подробнее эта процедура описана в листинге~\ref{AlgoTransformRows}. - -\begin{algorithm}[H] - \caption{Алгоритм трансформации строчек}\label{AlgoTransformRows} - \begin{algorithmic}[1] - \Procedure{TransformRows}{$M$} - \State{$T \gets extractLeftSubMatrix(M)$} - \State{$Ix, Iy \gets$ итераторы по индексам ненулевых элементов $T$} - \For{$i \in 0\dots|Iy|$} - \State{$R\gets M.getRow(Ix[i])$} - \State{$M'.setRow(Iy[i], R + M'.getRow(Iy[i]))$} - \EndFor - \EndProcedure - \end{algorithmic} -\end{algorithm} - -\pagebreak - -\subsection{Модификации алгоритма} - -Рассмотрим $V_{src}$ --- множество начальных вершин, состоящее из $r$ элементов. Для каждой начальной вершины $v_{src}^i \in V_{src}$ отметим соответствующие индексы в матрице $M$ единицами, получив матрицу $M(v_{src}^i)$, и построим матрицу $\mathfrak{M}$ следующим образом. - -\begin{equation} -\mathfrak{M}^{(k*r) \times (k + n)} = - \left[ - \begin{matrix} - M(v_{src}^1) \\ - M(v_{src}^2) \\ - M(\dots) \\ - M(v_{src}^r) \\ - \end{matrix} - \right] -\end{equation} - -Матрица $\mathfrak{M}$ собирается из множества матриц $M(v_{src}^i)$ и позволяет хранить информацию о том, из какой начальной вершины достигаются новые вершины во время обхода. - -\begin{algorithm}[t] - \caption{Модификация алгоритма для поиска конкретной исходной вершины}\label{BFSRPQ2} - \begin{algorithmic}[1] - \Procedure{BFSBasedRPQ}{$\mathcal{R}=\langle Q, \Sigma, P, F, q \rangle,\mathcal{G}=\langle V, E, L \rangle, V_{src}$} - \State $\mathcal{P}\gets~${Матрица смежности графа} - \State $\mathfrak{D}\gets Bool_\mathcal{R} \bigoplus Bool_\mathcal{G}$ - \State $\mathfrak{M}\gets CreateMasks(|Q|,|V|)$ - \State $\mathfrak{M}'\gets SetStartVerts(\mathfrak{M}, V_{src})$ - - \While{Матрица~$\mathfrak{M}$~меняется}{} - \State $\mathfrak{M}\gets \mathfrak{M}'\langle\neg\mathfrak{M}\rangle$ - \ForAll{$a\in (\Sigma \cap L)$} - \State $\mathfrak{M}'\gets \mathfrak{M}~$any.pair$~\mathfrak{D}$ - \ForAll{$M \in \mathfrak{M}'$} - \State $M\gets TransformRows(M)$ - \EndFor - \EndFor - \ForAll{$M_k \in \mathfrak{M}'$} - \State $Matrix\gets extractSubMatrix(M)$ - \State $V\gets Matrix.reduceVector()$ - \State $W\gets\mathcal{P}.getRow(k)$ - \State $\mathcal{P}.setRow(k, V+W)$ - \EndFor - \EndWhile - \State \textbf{return} $\mathcal{P}$ - \EndProcedure - \end{algorithmic} -\end{algorithm} - -В листинге~\ref{BFSRPQ2} представлен модифицированный алгоритм. Основное его отличие заключается в том, что для каждой достижимой вершины находится конкретная исходная вершина, из которой начинался обход. - -Таким образом, алгоритмы~\ref{BFSRPQ1}~и~\ref{BFSRPQ2} решают сформулированные в пункте \ref{sec:3.3} задачи достижимости. \ No newline at end of file diff --git a/tex/RegularLanguages.tex b/tex/RegularLanguages.tex deleted file mode 100644 index ccf39ac..0000000 --- a/tex/RegularLanguages.tex +++ /dev/null @@ -1,263 +0,0 @@ -\chapter{Регулярные языки} - - -В данном разделе мы обсудим регулярные языки --- класс, лежащий на самом нижнем уровне иерархии Хомского. -Будут рассмотрены основные способы задания таких языков: \textit{регулярные выражения}, \textit{конечные автоматы}, \textit{лево(право)линейные грамматики}. -Обсудим основные свойства регулярных языков, такие как замкнутость относительно различных операций, а также различные свойства соответствующих автоматов и грамматик. - - -\section{Регулярные выражения} - -Регулярные выражения --- один из классических способов задать регулярный язык\footnote{Замечание для программистов. Важно понимать, что речь идёт о формальной конструкции, а не о том, что называется регулярными выражениями в различных языках программирования или библиотеках, где под названием <<регулярные выражения>> могут скрываться конструкции, существенно более выразительные, чем обсуждаемые здесь.}. -Основывается этот способ на предложении синтаксиса для описания \textit{регулярных множеств}\footnote{Помним, что язык --- это множество слов.}. - -\begin{definition} - Регулярное множество (над алфавитом $\Sigma$) это: - \begin{itemize} - \item $\varnothing$ - \item $\{\varepsilon\}$ - \item $\{t\}$, $t \in \Sigma$ - \item $R_1 \cup R_2$, где $R_1$ и $R_2$ --- регулярные множества - \item $R_1 \cdot R_2$, где $R_1$ и $R_2$ --- регулярные множества - \item $R^*$, где $R$ --- регулярное множество - \end{itemize} -\end{definition} - -Для того, чтобы описывать такие множества, удобно пользоваться \textit{регулярными выражениями}. - -\begin{definition} - Регулярное выражение (над алфавитом $\Sigma$) это: - \begin{itemize} - \item $\varnothing$ - \item $\varepsilon$ - \item $t$, $t \in \Sigma$ - \item $R_1 \mid R_2$, где $R_1$ и $R_2$ --- регулярные выражения - \item $R_1 \cdot R_2$, где $R_1$ и $R_2$ --- регулярные выражения - \item $R^*$, где $R$ --- регулярное выражение - \item $(R)$, где $R$ --- регулярное выражение - \end{itemize} -\end{definition} - -Отметим несколько важных с прикладной точки зрения моментов. -Во-первых, часто используется расширенный синтаксис, в который добавляются конструкции не увеличивающие выразительную силу, но упрощающие запись. -Например, встречаются следующие расширения\footnote{Существуют и другие, однако их мы не будем использовать и, соответственно, рассматривать. Читатель может вспомнить, что называется регулярными выражениями в его любимом языке программирования и попробовать самостоятельно выразить имеющиеся там конструкции через базовые.}. -\begin{itemize} - \item $R? = R \mid \varepsilon$, где $R$ --- регулярное выражение. - \item $R^+ = R \cdot R^*$, где $R$ --- регулярное выражение. -\end{itemize} - -Во-вторых, конструкции $\varnothing$ и $\varepsilon$ используются крайне редко, особенно в случае расширенного синтаксиса, так как часто выражение, эквивалентное использующему данные конструкции, часто более компактно записывается с использованием расширенного синтаксиса. -В-третьих, оператор конкатенации часто опускается\footnote{Как и знак умножения во многих математических записях.}. - -Рассмотрим несколько примеров регулярных выражений. -\begin{example} - Регулярное выражение $a$ задаёт регулярное множество $\{a\}$ и, соответственно, язык из единственного слова $a$. -\end{example} - -\begin{example} - Регулярное выражение $ab$ задаёт регулярное множество $\{ab\}$ и, соответственно, язык из единственного слова $ab$. -\end{example} - - -\begin{example} - Регулярное выражение $a^*$ задаёт регулярное множество $$R = \bigcup_{i=0}^{\infty}{a^i} = \{\varepsilon, a, aa, aaa, \ldots \}$$ и, соответственно, бесконечный язык, содержащий для любого неотрицательного целого $n$ цепочку из символов $a$ длины $n$. -\end{example} - - -\begin{example} - $a^*b$ -\end{example} - -\begin{example} - $(a\mid b)^*$ -\end{example} - -\begin{example} - $(ab)^*c?$ -\end{example} - -\section{Конечные автоматы} - -\textit{Конечный автомат} --- вычислительная машина, которая имеет конечный набор состояний и может совершать переходы между ними, читая входные данные. -Важно отметить, что ни какой дополнительной памяти классический конечный автомат не имеет\footnote{Существуют автоматы с константной памятью, регистрами} и не производит дополнительных действий\footnote{Автоматы с записью на ленту, и т.д.}. - -\begin{definition}\label{def:NondeterminicticFiniteAutomata} - \textit{Недетерминированный конечный автомат, НКА} --- это пятёрка $M = \langle Q, Q_S, Q_F, \delta, \Sigma \rangle$, где - \begin{itemize} - \item $Q$ --- конечное множество состояний - \item $Q_S \in Q$ --- множество стартовых состояний - \item $Q_F \subseteq Q$ --- множество финальных состояний - \item $\delta \subseteq Q \times (\Sigma \cup \varepsilon) \times 2^Q$ --- функция переходов, а $\varepsilon \notin \Sigma$ - \item $\Sigma$ --- конечный алфавит - \end{itemize} -\end{definition} - -Так как нас интересуют конечные автоматы в контексте языков, то будем говорить, что на ленте автомата записано какое-то слово (или строка). -Иными словами, будем говорить, что автомат принимает на вход слово или строку. - - -Процесс вычислений, проделываемых конечным автоматом, удобно описывать в терминах переходов между \textit{конфигурациями}. - -\begin{definition} - Конфигурация $c$ конечного автомата $M = \langle Q, Q_S, Q_F, \delta, \Sigma \rangle$ --- это пара $(q,w)$, где $q\in Q$ --- это текущее состояние автомата, а $w \in \Sigma^*$ --- непросмотренная часть входной строки. -\end{definition} - -\begin{definition} - Будем говорить, что автомат $M = \langle Q, Q_S, Q_F, \delta, \Sigma \rangle$ может перейти из конфигурации $c_1 = (q_1,w_1)$ в конфигурацию $c_2 = (q_2,w_2)$, если - - $$c_2 \in \{(q_2,w_2) \mid w_1 = aw_2, (q_1,a, q_2) \in \delta\} \cup \{(q_2,w_1) \mid (q_1, \varepsilon, q_2) \in \delta\}.$$ - - Обозначать этот факт будем как $c_1 \to c_2$. -\end{definition} - -$$С_2 = \{(q_2,w_2) \mid w_1 = aw_2, (q_1,a, q_2) \in \delta\} \cup \{(q_2,w_1) \mid (q_1, \varepsilon, q_2) \in \delta\}.$$ -$$ c_1 \Rightarrow C_2 $$ - -Стартовая конфигурация. - -Финальная конфигурация. - -Ошибочная конфигурация. - -\begin{example} - Пример интерпретации конечного автомата. -\end{example} - - -\begin{definition}\label{def:DeterminicticFiniteAutomata} - \textit{Детерминированный конечный автомат (ДКА, Deterministic Finite Automata, DFA)} --- это пятёрка $M = \langle Q, q_S, Q_F, \delta, \Sigma \rangle$, где - \begin{itemize} - \item $Q$ --- конечное множество состояний - \item $q_S \in Q$ --- стартовое состояние - \item $Q_F \subseteq Q$ --- множество финальных состояний - \item $\delta \subseteq Q \times \Sigma \times Q$ --- функция переходов - \item $\Sigma$ --- конечный алфавит - \end{itemize} -\end{definition} - - -Заметим, что функцию переходов можно представить разными способами В зависимости от того, как именно представлена функция переходов: список троек, матрица, граф. - -\begin{example} - Пример КА. - \begin{tikzpicture} - - \end{tikzpicture} -\end{example} - - - -\begin{example} -Пример интерпретации конечного автомата. -\end{example} - -Построение КА по регулярному выражению и регулярному выражению по КА. На производных. - -Построение регулярного выражения по КА. - -Алгоритмы: проверка пустоты ... - -Примеры. - - -\section{Лево(право)линейные грамматики} - -Наложив некоторые ограничения на внешний вид правил грамматики можно получить грамматики, задающие регулярные языки. - -\begin{definition} - Грамматика $G=\langle \Sigma, N, P, S \rangle$ называется леволиненйной, если все её правила имеют вид $$N_i \to \alpha w $$, где $N_i \in N, \alpha \in \{\varepsilon\} \cup N, w \in \Sigma ^*$. -\end{definition} - -\begin{definition} - Грамматика $G=\langle \Sigma, N, P, S \rangle$ называется праволиненйной, если все её правила имеют вид $$N_i \to w \alpha$$, где $N_i \in N, \alpha \in \{\varepsilon\} \cup N, w \in \Sigma ^*$. -\end{definition} - - - -Ноам Хомский и Джордж Миллер в работе~\cite{chomsky1958finite} показали, что лево(право)линейные грамматики задают регулярные языки. -Приведём процедуры построения автомата по грамматике и наоборот, грамматики по автомату. - -Пусть дан конечный автомат $M = \langle \Sigma, Q, q_s, Q_f, \delta \rangle$. По нему можно построить праволинейную грамматику $G=\langle \Sigma, N, S, P \rangle$, где -\begin{itemize} - \item $N = Q$ - \item $P = \{ q_i \to t q_j \mid (q_i, t, q_j)\in \delta\} \cup \{ q_i \to \varepsilon \mid q_i \in Q_F\}$ - \item $S = q_s$ -\end{itemize} - -Аналогичным образом строится автомат по праволинейной грамматике. -Упростить процедуру можно если заранее привести правила к виду $N_i \to tN_j$, где $t\in \Sigma$, добавив необходимое количество новых нетерминалов: -правило вида $N_i \to twN_k$ преобразуется в два правила -\begin{align*} - N_i& \to tN_l\\ - N_l& \to wN_k \\ -\end{align*} -, после чего аналогично преобразуется правило для $N_l$. - -Пример построения грамматики по автомату. - -Автомат по грамматике. - -\section{Лемма о накачке} - -Лемма о накачке для регулярных языков позволяет проверить, что заданный язык не является регулярным. - -\begin{lemma} - Пусть $L$ --- регулярный язык над алфавитом $\Sigma$, тогда существует такое $n$, что для любого слова $\omega \in L$, $|\omega| \geq n$ найдутся слова $x,y,z\in \Sigma^*$, для которых верно: $xyz = \omega, y\neq \varepsilon,|xy|\leq n$ и для любого $k \geq 0$ $xy^kz \in L$. -\end{lemma} - -Идея доказательства леммы о накачке. - -\begin{enumerate} - \item Так как язык регулярный, то для него можно построить конечный автомат $M = \langle Q, q_s,Q_f, \delta, \Sigma \rangle$. В том числе, минимальный по количеству состояний. - \item В качестве $n$ возьмём $|Q| + 1$. - \item Легко заметить, что для любой цепочки $w \in L, |w| > n$ путь в автомате, соответствующий принятию данной цепочки, будет содержать хотя бы один цикл. - Действительно, в ориентированном графе с $k$ вершинами (а именно таким является автомат по построению) максимальная длина пути без повторных посещений вершин (соответственно, без циклов) не больше $k - 1$. - \item Выберем любой цикл. Он будет задавать искомые цепочки $x, y$ и $z$ так, как представлено на рисунке~\ref{fig:reg_lang_pumping_lemma}. - Заметим, что вход в цикл и выход из него в общем случае могут не совпадать, что даёт несколько вариантов разбиения пути на части, и на рисунке представлен лишь один из возможных. -\end{enumerate} - -\begin{figure} - \begin{center} - \begin{tikzpicture}[->] - \node[state, initial] (q1) {$q_1$}; - \node[state, right of=q1] (q2) {$q_2$}; - \node[state, accepting, right of=q2] (q3) {$q_3$}; - \node[state, above of=q2] (q4) {$q_4$}; - \draw (q1) edge[above, snake it] node{} (q2) - (q2) edge[bend right, snake it, side by side={red}{blue}] node{} (q4) - (q4) edge[bend right, snake it, color=blue] node[left]{$y$} (q2) - (q4) edge[above, snake it, color=green] node[right]{$z$} (q3) - (q1) edge[above, snake it, color=red] node{$x$} (q2) - ; - \end{tikzpicture} - \end{center} - \caption{Иллюстрация идеи доказательства леммы о накачке для регулярных языков: любой путь в графе, длина которого достаточно большая, может быть разбит на три части из леммы ($x$--- красный подпуть, $y$ --- синий, $z$ --- зелёный), а многократный проход по циклу $y$ позволяет ``накачать'' слово} - \label{fig:reg_lang_pumping_lemma} -\end{figure} - - -\section{Замкнутость регулярных языков относительно операций} - -\begin{theorem} - Регулярные языки замкнуты относительно перечисленных ниже операций. - \begin{enumerate} - \item Пересечение - \item Дополнение - \item Обращение - \item Разность - \end{enumerate} -\end{theorem} - -Линейная алгебра для работы с регулярными языками: пересечение, замыкание. - -Построение пересечения через тензорное произведение автоматов. - -Идея доказательства, что мы построили именно пересечение. - -Пересечение через синхронный обход в ширину. - -%\section{Вопросы и задачи} -% -%Построить базу. -% -%Научиться выполнять запросы через линейку. \ No newline at end of file diff --git a/tex/SPPF.tex b/tex/SPPF.tex deleted file mode 100644 index 0f02999..0000000 --- a/tex/SPPF.tex +++ /dev/null @@ -1,717 +0,0 @@ -\chapter{Сжатое представление леса разбора} - -Матричный алгоритм даёт нам ответ на вопрос о достижимости, но не предоставляет самих путей. -Что делать, если мы хотим построить все пути, удовлетворяющие ограничениям? - -Проблема в том, что искомое множество путей может быть бесконечным. -Можем ли мы предложить конечную структуру, однозначно описывающую такое множество? -Вспомним, что пересечение контекстно-свободного языка с регулярным --- это контекстно-свободный язык. -Мы знаем, что контекстно-свободный язык можно описать контекстно-свободной грамматикой, которая конечна. -Это и есть решение нашего вопроса. -Осталось только научиться строить такую грамматику. - -Прежде, чем двинуться дальше, рекомендуется вспомнить всё, что касается деревьев вывода~\ref{sect:DerivTree}. - -\section[Лес разбора как представление контекстно-свободной грамматики]{Лес разбора как представление контекстно-свободной грамматики\sectionmark{Лес разбора как представление КС грамматики}} -\sectionmark{Лес разбора как представление КС грамматики} - -Для начала нам потребуется внести некоторые изменения в конструкцию дерева вывода. - -Во-первых, заметим, что в дереве вывода каждый узел соответствует выводу какой-то подстроки с известными позициями начала и конца. -Давайте будем сохранять эту информацию в узлах дерева. -Таким образом, метка любого узла это тройка вида $(i,q,j)$, где $i$ --- координата начала подстроки, соответствующей этому узлу, $j$ --- координата конца, $q \in \Sigma \cup N$ --- метка как в исходном определении. - -Во-вторых, заметим, что внутренний узел со своими сыновьями связаны с продукцией в грамматике: узел появляется благодаря применению конкретной продукции в процессе вывода. -Давайте занумеруем все продукции в грамматике и добавим в дерево вывода ещё один тип узлов (дополнительные узлы), в которых будем хранить номер применённой продукции. -Получим следующую конструкцию: непосредственный предок дополнительного узла --- это левая часть продукции, а непосредственные сыновья дополнительного узла --- это правая часть продукции. - -\begin{example} - Построим модифицированное дерево вывода цепочки $_0a_1b_2a_3b_4a_5b_6$ в грамматике - - \begin{align*} - G_0 = \langle \{a,b\}, \{S\}, S, \{ & \\ - & \ \ (0) S \to a \ S \ b \ S, \\ - & \ \ (1) S \to \varepsilon \\ - & \} \rangle - \end{align*} - - - -\begin{center} -\resizebox{0.9\textwidth}{!}{ -\begin{tikzpicture}[shorten >=1pt,node distance=1.2cm] - \node[symbol_node] (s_0_6) {$(0,S,6)$}; - \node[prod_node] (p_0_1) [below=of s_0_6] {$0$}; - \node[prod_node,draw=none] (dummy1) [below =of p_0_1] {}; - \node[symbol_node] (s_1_1) [below left=of p_0_1] {$(1,S,1)$}; - \node[symbol_node] (s_2_6) [below right=of p_0_1] {$(2,S,6)$}; - - \node[prod_node] (p_0_2) [below right=of s_2_6] {$0$}; - - \node[symbol_node] (s_3_3) [below left=of p_0_2] {$(3,S,3)$}; - \node[symbol_node] (s_4_6) [below right=of p_0_2] {$(4,S,6)$}; - - \node[prod_node] (p_0_3) [below right =of s_4_6] {0}; - - \node[symbol_node] (s_5_5) [below =of p_0_3] {$(5,S,5)$}; - \node[symbol_node] (s_6_6) [below right=of p_0_3] {$(6,S,6)$}; - -% \node[state,draw=none] (dummy1) [below =of s_0_6] {}; -% \node[state,draw=none] (dummy2) [below =of dummy1] {}; - -% \node[state,draw=none] (dummy3) [below left=of p_0_3] {}; -% \node[state,draw=none] (dummy4) [below right=of p_0_4] {}; - - -% \node[symbol_node] (s_0_2) [left=of dummy3] {$(0,S,2)$}; -% -% \node[symbol_node] (s_2_4) [between=s_0_2 and s_4_6] {$(2,S,4)$}; - - - \node[prod_node] (p_1_1) [below left =of s_1_1] {$1$}; - \node[prod_node] (p_1_2) [below left =of s_3_3] {$1$}; - \node[prod_node] (p_1_3) [below =of s_5_5] {$1$}; - \node[prod_node] (p_1_4) [below right=of s_6_6] {$1$}; - - - -% \node[prod_node] (p_2_1) [below =of s_1_1] {$2$}; -% \node[prod_node] (p_2_2) [below =of s_3_3] {$2$}; -% \node[prod_node] (p_2_3) [below =of s_5_5] {$2$}; - - \node[symbol_node] (eps_6_6) [below right=of p_1_4] {$(6,\varepsilon,6)$}; - \node[symbol_node] (b_5_6) [left=of eps_6_6] {$(5,b,6)$}; - \node[symbol_node] (eps_5_5) [left =of b_5_6] {$(5,\varepsilon,5)$}; - \node[symbol_node] (a_4_5) [left=of eps_5_5] {$(4,a,5)$}; - \node[symbol_node] (b_3_4) [left=of a_4_5] {$(3,b,4)$}; - \node[symbol_node] (eps_3_3) [left =of b_3_4] {$(3,\varepsilon,3)$}; - \node[symbol_node] (a_2_3) [left=of eps_3_3] {$(2,a,3)$}; - \node[symbol_node] (b_1_2) [left=of a_2_3] {$(1,b,2)$}; - \node[symbol_node] (eps_1_1) [left =of b_1_2] {$(1,\varepsilon,1)$}; - \node[symbol_node] (a_0_1) [left=of eps_1_1] {$(0,a,1)$}; - - - \path[->] - (s_0_6) edge (p_0_1) - - (p_0_1) edge [bend right] (a_0_1) - (p_0_1) edge (s_1_1) - (p_0_1) edge (b_1_2) - (p_0_1) edge (s_2_6) - - (s_2_6) edge (p_0_2) - - (p_0_2) edge [bend right] (a_2_3) - (p_0_2) edge (s_3_3) - (p_0_2) edge (b_3_4) - (p_0_2) edge (s_4_6) - - (s_4_6) edge (p_0_3) - - (p_0_3) edge (a_4_5) - (p_0_3) edge (s_5_5) - (p_0_3) edge (b_5_6) - (p_0_3) edge (s_6_6) - - (s_1_1) edge (p_1_1) - (p_1_1) edge (eps_1_1) - - (s_3_3) edge (p_1_2) - (p_1_2) edge (eps_3_3) - - (s_5_5) edge (p_1_3) - (p_1_3) edge (eps_5_5) - - (s_6_6) edge (p_1_4) - (p_1_4) edge (eps_6_6) - - - ; -\end{tikzpicture} -} -\end{center} - - -\end{example} - - -Сохраняемая нами дополнительная информация позволит переиспользовать узлы в том случае, если деревьев вывода оказалось несколько (в случае неоднозначной грамматики). -При этом мы можем не бояться, что переиспользование узлов может привести к появлению ранее несуществовавших деревьев вывода, так как дополнительная информация позволяет делать только ``безопасные'' склейки и затем восстанавливать только корректные деревья. Таким образом, мы можем представить лес вывода в виде единой структуры данных без дублирования информации. - - -\begin{example} - Сжатие леса вывода. - Построим несколько деревьев вывода цепочки $_0a_1b_2a_3b_4a_5b_6$ в грамматике - - \begin{align*} - G_1 = \langle \{a,b\}, \{S\}, S, \{ & \\ - & \ \ (0) S \to S S, \\ - & \ \ (1) S \to a \ S \ b, \\ - & \ \ (2) S \to \varepsilon \\ - & \} \rangle - \end{align*} - -Предположим, что мы строим левосторонний вывод. -Тогда после первого применения продукции 0 у нас есть два варианта переписывания первого нетерминала: либо с применением продукции 0, либо с применением продукции 1: -\begin{align*} -&\textbf{S} \xrightarrow{0} \textbf{S}S \xrightarrow{0} \textbf{S}SS \xrightarrow{1} a\textbf{S}bSS \xrightarrow{2} ab\textbf{S}S \xrightarrow{1} aba\textbf{S}bS \xrightarrow{2} abab\textbf{S} \xrightarrow{1} ababa\textbf{S}b \xrightarrow{2} ababab -\\ -&\textbf{S} \xrightarrow{0} \textbf{S}S \xrightarrow{1} a\textbf{S}bS \xrightarrow{2} ab\textbf{S} \xrightarrow{0} ab\textbf{S}S \xrightarrow{1} aba\textbf{S}bS \xrightarrow{2} abab\textbf{S} \xrightarrow{1} ababa\textbf{S}b \xrightarrow{2} ababab -\end{align*} - -Сначала рассмотрим первый вариант (применили переписывание по продукции 0). -Все остальные шаги вывода деретерминированы и в результате мы получим следующее дерево разбора: - -\begin{center} -\resizebox{0.9\textwidth}{!}{ -\begin{tikzpicture}[shorten >=1pt,on grid,auto,node distance=1.8cm] - \node[symbol_node] (s_0_6) {$(0,S,6)$}; - \node[prod_node] (p_0_1) [below left=of s_0_6] {$0$}; - \node[prod_node,draw=none] (p_0_2) [below right=of s_0_6] {}; - \node[symbol_node] (s_0_4) [below left=of p_0_1] {$(0,S,4)$}; - \node[symbol_node,draw=none] (s_2_6) [below right=of p_0_2] {}; - \node[prod_node] (p_0_3) [below =of s_0_4] {$0$}; - \node[prod_node,draw=none] (p_0_4) [below =of s_2_6] {}; - - \node[state,draw=none] (dummy1) [below =of s_0_6] {}; - \node[state,draw=none] (dummy2) [below =of dummy1] {}; - - \node[state,draw=none] (dummy3) [below left=of p_0_3] {}; - \node[state,draw=none] (dummy4) [below right=of p_0_4] {}; - - - \node[symbol_node] (s_0_2) [left=of dummy3] {$(0,S,2)$}; - \node[symbol_node] (s_4_6) [right=of dummy4] {$(4,S,6)$}; - \node[symbol_node] (s_2_4) [between=s_0_2 and s_4_6] {$(2,S,4)$}; - - \node[prod_node] (p_1_1) [below =of s_0_2] {$1$}; - \node[prod_node] (p_1_2) [below =of s_2_4] {$1$}; - \node[prod_node] (p_1_3) [below =of s_4_6] {$1$}; - - \node[symbol_node] (s_1_1) [below =of p_1_1] {$(1,S,1)$}; - \node[symbol_node] (s_3_3) [below =of p_1_2] {$(3,S,3)$}; - \node[symbol_node] (s_5_5) [below =of p_1_3] {$(5,S,5)$}; - - \node[prod_node] (p_2_1) [below =of s_1_1] {$2$}; - \node[prod_node] (p_2_2) [below =of s_3_3] {$2$}; - \node[prod_node] (p_2_3) [below =of s_5_5] {$2$}; - - \node[symbol_node] (eps_1_1) [below =of p_2_1] {$(1,\varepsilon,1)$}; - \node[symbol_node] (eps_3_3) [below =of p_2_2] {$(3,\varepsilon,3)$}; - \node[symbol_node] (eps_5_5) [below =of p_2_3] {$(5,\varepsilon,5)$}; - - \node[symbol_node] (a_0_1) [left=of eps_1_1] {$(0,a,1)$}; - \node[symbol_node] (a_2_3) [left=of eps_3_3] {$(2,a,3)$}; - \node[symbol_node] (a_4_5) [left=of eps_5_5] {$(4,a,5)$}; - - \node[symbol_node] (b_1_2) [right=of eps_1_1] {$(1,b,2)$}; - \node[symbol_node] (b_3_4) [right=of eps_3_3] {$(3,b,4)$}; - \node[symbol_node] (b_5_6) [right=of eps_5_5] {$(5,b,6)$}; - - - \path[->] - (s_0_6) edge (p_0_1) -% (s_0_6) edge (p_0_2) - (p_0_1) edge (s_0_4) - (p_0_1) edge (s_4_6) -% (p_0_2) edge (s_0_2) -% (p_0_2) edge (s_2_6) - (s_0_4) edge (p_0_3) -% (s_2_6) edge (p_0_4) - (p_0_3) edge (s_0_2) - (p_0_3) edge (s_2_4) -% (p_0_4) edge (s_2_4) -% (p_0_4) edge (s_4_6) - - (s_0_2) edge (p_1_1) - (s_2_4) edge (p_1_2) - (s_4_6) edge (p_1_3) - - (p_1_1) edge [bend right] (a_0_1) - (p_1_1) edge (s_1_1) - (p_1_1) edge [bend left] (b_1_2) - - (p_1_2) edge [bend right] (a_2_3) - (p_1_2) edge (s_3_3) - (p_1_2) edge [bend left] (b_3_4) - - (p_1_3) edge [bend right] (a_4_5) - (p_1_3) edge (s_5_5) - (p_1_3) edge [bend left] (b_5_6) - - (s_1_1) edge (p_2_1) - (p_2_1) edge (eps_1_1) - - (s_3_3) edge (p_2_2) - (p_2_2) edge (eps_3_3) - - (s_5_5) edge (p_2_3) - (p_2_3) edge (eps_5_5) - - ; -\end{tikzpicture} -} -\end{center} - -Теперь рассмотрим второй вариант --- применить продукцию 1. -Остальные шаги вывода всё также детерминированы. -В результате мы получим следующее дерево вывода: - -\begin{center} -\resizebox{0.9\textwidth}{!}{ -\begin{tikzpicture}[shorten >=1pt,on grid,auto,node distance=1.8cm] - \node[symbol_node] (s_0_6) {$(0,S,6)$}; - \node[prod_node,draw=none] (p_0_1) [below left=of s_0_6] {}; - \node[prod_node] (p_0_2) [below right=of s_0_6] {$0$}; - \node[symbol_node,draw=none] (s_0_4) [below left=of p_0_1] {}; - \node[symbol_node] (s_2_6) [below right=of p_0_2] {$(2,S,6)$}; - \node[prod_node,draw=none] (p_0_3) [below =of s_0_4] {}; - \node[prod_node] (p_0_4) [below =of s_2_6] {$0$}; - - \node[state,draw=none] (dummy1) [below =of s_0_6] {}; - \node[state,draw=none] (dummy2) [below =of dummy1] {}; - - \node[state,draw=none] (dummy3) [below left=of p_0_3] {}; - \node[state,draw=none] (dummy4) [below right=of p_0_4] {}; - - - \node[symbol_node] (s_0_2) [left=of dummy3] {$(0,S,2)$}; - \node[symbol_node] (s_4_6) [right=of dummy4] {$(4,S,6)$}; - \node[symbol_node] (s_2_4) [between=s_0_2 and s_4_6] {$(2,S,4)$}; - - \node[prod_node] (p_1_1) [below =of s_0_2] {$1$}; - \node[prod_node] (p_1_2) [below =of s_2_4] {$1$}; - \node[prod_node] (p_1_3) [below =of s_4_6] {$1$}; - - \node[symbol_node] (s_1_1) [below =of p_1_1] {$(1,S,1)$}; - \node[symbol_node] (s_3_3) [below =of p_1_2] {$(3,S,3)$}; - \node[symbol_node] (s_5_5) [below =of p_1_3] {$(5,S,5)$}; - - \node[prod_node] (p_2_1) [below =of s_1_1] {$2$}; - \node[prod_node] (p_2_2) [below =of s_3_3] {$2$}; - \node[prod_node] (p_2_3) [below =of s_5_5] {$2$}; - - \node[symbol_node] (eps_1_1) [below =of p_2_1] {$(1,\varepsilon,1)$}; - \node[symbol_node] (eps_3_3) [below =of p_2_2] {$(3,\varepsilon,3)$}; - \node[symbol_node] (eps_5_5) [below =of p_2_3] {$(5,\varepsilon,5)$}; - - \node[symbol_node] (a_0_1) [left=of eps_1_1] {$(0,a,1)$}; - \node[symbol_node] (a_2_3) [left=of eps_3_3] {$(2,a,3)$}; - \node[symbol_node] (a_4_5) [left=of eps_5_5] {$(4,a,5)$}; - - \node[symbol_node] (b_1_2) [right=of eps_1_1] {$(1,b,2)$}; - \node[symbol_node] (b_3_4) [right=of eps_3_3] {$(3,b,4)$}; - \node[symbol_node] (b_5_6) [right=of eps_5_5] {$(5,b,6)$}; - - - \path[->] - %(s_0_6) edge (p_0_1) - (s_0_6) edge (p_0_2) - %(p_0_1) edge (s_0_4) - %(p_0_1) edge (s_4_6) - (p_0_2) edge (s_0_2) - (p_0_2) edge (s_2_6) - %(s_0_4) edge (p_0_3) - (s_2_6) edge (p_0_4) - %(p_0_3) edge (s_0_2) - %(p_0_3) edge (s_2_4) - (p_0_4) edge (s_2_4) - (p_0_4) edge (s_4_6) - - (s_0_2) edge (p_1_1) - (s_2_4) edge (p_1_2) - (s_4_6) edge (p_1_3) - - (p_1_1) edge [bend right] (a_0_1) - (p_1_1) edge (s_1_1) - (p_1_1) edge [bend left] (b_1_2) - - (p_1_2) edge [bend right] (a_2_3) - (p_1_2) edge (s_3_3) - (p_1_2) edge [bend left] (b_3_4) - - (p_1_3) edge [bend right] (a_4_5) - (p_1_3) edge (s_5_5) - (p_1_3) edge [bend left] (b_5_6) - - (s_1_1) edge (p_2_1) - (p_2_1) edge (eps_1_1) - - (s_3_3) edge (p_2_2) - (p_2_2) edge (eps_3_3) - - (s_5_5) edge (p_2_3) - (p_2_3) edge (eps_5_5) - - ; -\end{tikzpicture} -} -\end{center} - -В двух построенных деревьях большое количество одинаковых узлов. -Построим структуру, которая содержит оба дерева и при этом никакие нетерминальные и терминальные узлы не встречаются дважды. -В результате мы получим следующий граф: - -\begin{center} -\resizebox{0.9\textwidth}{!}{ -\begin{tikzpicture}[shorten >=1pt,on grid,auto,node distance=1.8cm] - \node[symbol_node] (s_0_6) {$(0,S,6)$}; - \node[prod_node] (p_0_1) [below left=of s_0_6] {$0$}; - \node[prod_node] (p_0_2) [below right=of s_0_6] {$0$}; - \node[symbol_node] (s_0_4) [below left=of p_0_1] {$(0,S,4)$}; - \node[symbol_node] (s_2_6) [below right=of p_0_2] {$(2,S,6)$}; - \node[prod_node] (p_0_3) [below =of s_0_4] {$0$}; - \node[prod_node] (p_0_4) [below =of s_2_6] {$0$}; - - \node[state,draw=none] (dummy1) [below =of s_0_6] {}; - \node[state,draw=none] (dummy2) [below =of dummy1] {}; - - \node[state,draw=none] (dummy3) [below left=of p_0_3] {}; - \node[state,draw=none] (dummy4) [below right=of p_0_4] {}; - - - \node[symbol_node] (s_0_2) [left=of dummy3] {$(0,S,2)$}; - \node[symbol_node] (s_4_6) [right=of dummy4] {$(4,S,6)$}; - \node[symbol_node] (s_2_4) [between=s_0_2 and s_4_6] {$(2,S,4)$}; - - \node[prod_node] (p_1_1) [below =of s_0_2] {$1$}; - \node[prod_node] (p_1_2) [below =of s_2_4] {$1$}; - \node[prod_node] (p_1_3) [below =of s_4_6] {$1$}; - - \node[symbol_node] (s_1_1) [below =of p_1_1] {$(1,S,1)$}; - \node[symbol_node] (s_3_3) [below =of p_1_2] {$(3,S,3)$}; - \node[symbol_node] (s_5_5) [below =of p_1_3] {$(5,S,5)$}; - - \node[prod_node] (p_2_1) [below =of s_1_1] {$2$}; - \node[prod_node] (p_2_2) [below =of s_3_3] {$2$}; - \node[prod_node] (p_2_3) [below =of s_5_5] {$2$}; - - \node[symbol_node] (eps_1_1) [below =of p_2_1] {$(1,\varepsilon,1)$}; - \node[symbol_node] (eps_3_3) [below =of p_2_2] {$(3,\varepsilon,3)$}; - \node[symbol_node] (eps_5_5) [below =of p_2_3] {$(5,\varepsilon,5)$}; - - \node[symbol_node] (a_0_1) [left=of eps_1_1] {$(0,a,1)$}; - \node[symbol_node] (a_2_3) [left=of eps_3_3] {$(2,a,3)$}; - \node[symbol_node] (a_4_5) [left=of eps_5_5] {$(4,a,5)$}; - - \node[symbol_node] (b_1_2) [right=of eps_1_1] {$(1,b,2)$}; - \node[symbol_node] (b_3_4) [right=of eps_3_3] {$(3,b,4)$}; - \node[symbol_node] (b_5_6) [right=of eps_5_5] {$(5,b,6)$}; - - - \path[->] - (s_0_6) edge (p_0_1) - (s_0_6) edge (p_0_2) - (p_0_1) edge (s_0_4) - (p_0_1) edge (s_4_6) - (p_0_2) edge (s_0_2) - (p_0_2) edge (s_2_6) - (s_0_4) edge (p_0_3) - (s_2_6) edge (p_0_4) - (p_0_3) edge (s_0_2) - (p_0_3) edge (s_2_4) - (p_0_4) edge (s_2_4) - (p_0_4) edge (s_4_6) - - (s_0_2) edge (p_1_1) - (s_2_4) edge (p_1_2) - (s_4_6) edge (p_1_3) - - (p_1_1) edge [bend right] (a_0_1) - (p_1_1) edge (s_1_1) - (p_1_1) edge [bend left] (b_1_2) - - (p_1_2) edge [bend right] (a_2_3) - (p_1_2) edge (s_3_3) - (p_1_2) edge [bend left] (b_3_4) - - (p_1_3) edge [bend right] (a_4_5) - (p_1_3) edge (s_5_5) - (p_1_3) edge [bend left] (b_5_6) - - (s_1_1) edge (p_2_1) - (p_2_1) edge (eps_1_1) - - (s_3_3) edge (p_2_2) - (p_2_2) edge (eps_3_3) - - (s_5_5) edge (p_2_3) - (p_2_3) edge (eps_5_5) - - ; -\end{tikzpicture} -} -\end{center} - - -\end{example} - - -Мы получили очень простой вариант сжатого представления леса разбора (Shared Packed Parse Forest, SPPF). -Впервые подобная идея была предложена Джоаном Рекерсом в его кандидатской диссертации~\cite{SPPF}. -В дальнейшем она нашла широкое применение в обобщённом (generalized) синтаксическом анализе и получила серьёзное развитие. -В частности, наш вариант, хоть и позволяет избежать экспоненциального разрастания леса разбора, всё же не является оптимальным. -Оптимальное асимптотическое поведение достигается при использовании бинаризованного SPPF~\cite{Billot:1989:SSF:981623.981641} --- в этом случае объём леса составляет $O(n^3)$, где $n$ --- это длина входной строки. - -Различные модификации SPPF применяются в таких алгоритмах синтаксического анализа, как RNGLR~\cite{Scott:2006:RNG:1146809.1146810}, бинаризованная верся SPPF в BRNGLR~\cite{Scott:2007:BCT:1289813.1289815} и GLL~\cite{Scott:2010:GP:1860132.1860320,10.1007/978-3-662-46663-6_5}\footnote{Ещё немного полезной информации про SPPF: \url{http://www.bramvandersanden.com/post/2014/06/shared-packed-parse-forest/}.}. - -В действительности SPPF может содержать в себе циклы. Для линейного входа их можно получить, когда есть возможность выводить по грамматике бесконечные эпсилон-цепочки. Циклы будут вырожденными, но они будут. - -Мы, кроме традиционного использования, будем применять SPPF для представления результатов КС запросов к графам. - -В графе может существовать множество способов получить путь из одной вершины в другую. И точно так же при построении деревьев вывода путей может появиться несколько одинаковых нетерминалов, получаемых в разных деревьях по-разному. При объединении в SPPF может оказаться, что какой-то путь из вершины $a$ в вершину $b$ является подпутем другого пути из вершины $a$ в вершину $b$, просто более длинного. То есть появятся циклические зависимости. - -\begin{example} - Рассмотрим пример SPPF для задачи поиска путей с КС ограничениями. - Пусть дан граф $\mathcal{G}:$ - - \begin{center} - \input{figures/graph/graph0.tex} - \end{center} - - Дана грамматика - - \begin{align*} - G = \langle \{a,b\}, \{S\}, S, \ & \{ \\ - & \ \ (0)\ S \to a \ S \ b, \\ - & \ \ (1)\ S \to a \ b, \\ - \ & \} \rangle - \end{align*} - - - Попробуем найти все пути из вершины 2 в вершину 2, выводимые из нетерминала $S$. - Проверить наличие такого пути можно используя уже известные нам алгоритмы, однако сами пути пока будем строить ``методом пристального взгляда''. Найдем один из них. Пусть это будет - $$2 \xrightarrow{a} 0 \xrightarrow{a} 1 \xrightarrow{a} 2 \xrightarrow{a} 0 \xrightarrow{a} 1 \xrightarrow{a} 2 \xrightarrow{b} 3 \xrightarrow{b} 2 \xrightarrow{b} 3 \xrightarrow{b} 2 \xrightarrow{b} 3 \xrightarrow{b} 2. - $$ - Построим дерево его вывода. - - \begin{center} - \resizebox{0.3\textwidth}{!}{ - \begin{tikzpicture}[shorten >=1pt,on grid,auto,node distance=1.8cm] - \node[symbol_node] (s_2_2) {$(2,S,2)$}; - - \node[prod_node] (p_0_1) [below =of s_0_6] {$0$}; - \node[symbol_node] (s_0_3) [below =of p_0_1] {$(0,S,3)$}; - \node[symbol_node] (a_2_0_1) [left =of s_0_3] {$(2,a,0)$}; - \node[symbol_node] (b_3_2_1) [right=of s_0_3] {$(3,b,2)$}; - - \node[prod_node] (p_0_2) [below =of s_0_3] {$0$}; - \node[symbol_node] (s_1_2) [below =of p_0_2] {$(1,S,2)$}; - \node[symbol_node] (a_0_1_1) [left =of s_1_2] {$(0,a,1)$}; - \node[symbol_node] (b_2_3_1) [right=of s_1_2] {$(2,b,3)$}; - - \node[prod_node] (p_0_3) [below =of s_1_2] {$0$}; - \node[symbol_node] (s_2_3) [below =of p_0_3] {$(2,S,3)$}; - \node[symbol_node] (a_1_2_1) [left =of s_2_3] {$(1,a,2)$}; - \node[symbol_node] (b_3_2_2) [right=of s_2_3] {$(3,b,2)$}; - - \node[prod_node] (p_0_4) [below =of s_2_3] {$0$}; - \node[symbol_node] (s_0_2) [below =of p_0_4] {$(0,S,2)$}; - \node[symbol_node] (a_2_0_2) [left =of s_0_2] {$(2,a,0)$}; - \node[symbol_node] (b_2_3_2) [right=of s_0_2] {$(2,b,3)$}; - - \node[prod_node] (p_0_5) [below =of s_0_2] {$0$}; - \node[symbol_node] (s_1_3) [below =of p_0_5] {$(1,S,3)$}; - \node[symbol_node] (a_0_1_2) [left =of s_1_3] {$(0,a,1)$}; - \node[symbol_node] (b_3_2_3) [right=of s_1_3] {$(3,b,2)$}; - - \node[prod_node] (p_1_1) [below =of s_1_3] {$1$}; - \node[symbol_node] (a_1_2_2) [below left =of p_1_1] {$(1,a,2)$}; - \node[symbol_node] (b_2_3_3) [below right=of p_1_1] {$(2,b,3)$}; - - \path[->] - (s_2_2) edge (p_0_1) - - (p_0_1) edge (s_0_3) - (p_0_1) edge (a_2_0_1) - (p_0_1) edge (b_3_2_1) - - (s_0_3) edge (p_0_2) - - (p_0_2) edge (s_1_2) - (p_0_2) edge (a_0_1_1) - (p_0_2) edge (b_2_3_1) - - (s_1_2) edge (p_0_3) - - (p_0_3) edge (s_2_3) - (p_0_3) edge (a_1_2_1) - (p_0_3) edge (b_3_2_2) - - (s_2_3) edge (p_0_4) - - (p_0_4) edge (s_0_2) - (p_0_4) edge (a_2_0_2) - (p_0_4) edge (b_2_3_2) - - (s_0_2) edge (p_0_5) - - (p_0_5) edge (s_1_3) - (p_0_5) edge (a_0_1_2) - (p_0_5) edge (b_3_2_3) - - (s_1_3) edge (p_1_1) - - (p_1_1) edge (a_1_2_2) - (p_1_1) edge (b_2_3_3) - - ; - \end{tikzpicture} - } - \end{center} - - Мы построили дерево вывода для одного пути из вершины 2 в неё же. - Но можно заметить, что таких путей бесконечно много: мы можем бесконечное число раз повторять уже выполненный обход и получать всё более длинные пути. - В терминах дерева вывода это будет означать, что к узлу $_1S_3$ мы добавим сына, соответствующего применению продукции 0, а не 1 для нетерминала $S$. - В таком случае мы получим узел $_2S_2$, который уже существует в дереве и таким образом замкнём цикл. - - \begin{center} - \resizebox{0.5\textwidth}{!}{ - \begin{tikzpicture}[shorten >=1pt,on grid,auto,node distance=1.8cm] - \node[symbol_node] (s_2_2) {$(2,S,2)$}; - - \node[prod_node] (p_0_1) [below =of s_0_6] {$0$}; - \node[symbol_node] (s_0_3) [below =of p_0_1] {$(0,S,3)$}; - \node[symbol_node] (a_2_0_1) [left =of s_0_3] {$(2,a,0)$}; - \node[symbol_node] (b_3_2_1) [right=of s_0_3] {$(3,b,2)$}; - - \node[prod_node] (p_0_2) [below =of s_0_3] {$0$}; - \node[symbol_node] (s_1_2) [below =of p_0_2] {$(1,S,2)$}; - \node[symbol_node] (a_0_1_1) [left =of s_1_2] {$(0,a,1)$}; - \node[symbol_node] (b_2_3_1) [right=of s_1_2] {$(2,b,3)$}; - - \node[prod_node] (p_0_3) [below =of s_1_2] {$0$}; - \node[symbol_node] (s_2_3) [below =of p_0_3] {$(2,S,3)$}; - \node[symbol_node] (a_1_2_1) [left =of s_2_3] {$(1,a,2)$}; - \node[symbol_node] (b_3_2_2) [right=of s_2_3] {$(3,b,2)$}; - - \node[prod_node] (p_0_4) [below =of s_2_3] {$0$}; - \node[symbol_node] (s_0_2) [below =of p_0_4] {$(0,S,2)$}; - \node[symbol_node] (a_2_0_2) [left =of s_0_2] {$(2,a,0)$}; - \node[symbol_node] (b_2_3_2) [right=of s_0_2] {$(2,b,3)$}; - - \node[prod_node] (p_0_5) [below =of s_0_2] {$0$}; - \node[symbol_node] (s_1_3) [below =of p_0_5] {$(1,S,3)$}; - \node[symbol_node] (a_0_1_2) [left =of s_1_3] {$(0,a,1)$}; - \node[symbol_node] (b_3_2_3) [right=of s_1_3] {$(3,b,2)$}; - - \node[state,draw=none] (dummy1) [below left=of s_1_3] {}; - \node[state,draw=none] (dummy2) [below right=of s_1_3] {}; - \node[prod_node] (p_1_1) [left =of dummy1] {$1$}; - \node[symbol_node] (a_1_2_2) [below left =of p_1_1] {$(1,a,2)$}; - \node[symbol_node] (b_2_3_3) [below right=of p_1_1] {$(2,b,3)$}; - \node[prod_node] (p_0_6) [right =of dummy2] {$0$}; - \node[symbol_node] (a_1_2_3) [below left =of p_0_6] {$(1,a,2)$}; - \node[symbol_node] (b_2_3_4) [below right=of p_0_6] {$(2,b,3)$}; - - - \path[->] - (s_2_2) edge (p_0_1) - - (p_0_1) edge (s_0_3) - (p_0_1) edge (a_2_0_1) - (p_0_1) edge (b_3_2_1) - - (s_0_3) edge (p_0_2) - - (p_0_2) edge (s_1_2) - (p_0_2) edge (a_0_1_1) - (p_0_2) edge (b_2_3_1) - - (s_1_2) edge (p_0_3) - - (p_0_3) edge (s_2_3) - (p_0_3) edge (a_1_2_1) - (p_0_3) edge (b_3_2_2) - - (s_2_3) edge (p_0_4) - - (p_0_4) edge (s_0_2) - (p_0_4) edge (a_2_0_2) - (p_0_4) edge (b_2_3_2) - - (s_0_2) edge (p_0_5) - - (p_0_5) edge (s_1_3) - (p_0_5) edge (a_0_1_2) - (p_0_5) edge (b_3_2_3) - - (s_1_3) edge (p_1_1) - - (p_1_1) edge (a_1_2_2) - (p_1_1) edge (b_2_3_3) - - (s_1_3) edge (p_0_6) - - (p_0_6) edge (a_1_2_3) - (p_0_6) edge (b_2_3_4) - (p_0_6) edge [bend right] (s_2_2) - - ; - \end{tikzpicture} - } - \end{center} - - Таким образом мы построили SPPF. Обойдя эту структуру необходимое количество раз, мы можем получить любой путь, удовлетворяющий условию. Более того, в полученном графе можно получать любые другие пути по соответствующим нетерминалам и парам вершин, содержащимся в узлах леса. - \end{example} - - \begin{note} - SPPF построенный для данной контекстно-свободной грамматики $G$ и графа $\mathcal{G}$ - \begin{enumerate} - \item содержит терминальный узел вида $(i,t_k,j)$ тогда и только тогда, когда в графе $\mathcal{G}$ есть ребро $(i,t_k,j)$; - \item содержит нетерминальный узел вида $(i,S_k,j)$ тогда и только тогда, когда в графе $\mathcal{G}$ есть путь из вершины $i$ в вершину $j$, выводимый из нетерминала $S_k$ в грамматике $G$. - \end{enumerate} - \end{note} - - Осталось увидеть, что SPPF является представлением контекстно-свободной грамматики, описывающей результат пересечения исходных графа и грамматики. Для этого просто построим грамматику $G_{\textit{SPPF}} = \langle \Sigma_{\textit{SPPF}}, N_{\textit{SPPF}}, S_{\textit{SPPF}}, P_{\textit{SPPF}}\rangle$ по SPPF следующим образом: - \begin{itemize} - \item $\Sigma_{\textit{SPPF}}$ --- все листья SPPF; - \item $N_{\textit{SPPF}}$ --- все нетерминальные узлы SPPF; - \item $S_{\textit{SPPF}}$ --- нетерминал, соответствующий пути, который нас будет интересовать; - \item $P_{\textit{SPPF}}$ --- для каждого дополнительного узла (с номером продукции) добавляем продукцию, левая часть которой --- непосредственный предок этого узла, а правая чать --- непосредственные потомки. - \end{itemize} - - \begin{example} - Построим грамматику для полученного SPPF: - \begin{align*} - (0)\ _2S_2 & \to\ _2a_0\ _0S_3\ _3b_2 &(4)\ _0S_2 \to\ &_0a_1\ _1S_3\ _3b_2 \\ - (1)\ _0S_3 & \to\ _0a_1\ _1S_2\ _2b_3 &(5)\ _1S_3 \to\ &_1a_2\ _2S_2\ _2b_3 \\ - (2)\ _1S_2 & \to\ _1a_2\ _2S_3\ _3b_2 &(6)\ _1S_3 \to\ &_1a_2\ _2b_3 \\ - (3)\ _2S_3 & \to\ _2a_0\ _0S_2\ _2b_3 & - \end{align*} - Видим, что для одного единственного нетерминала $_1S_3$ существует 2 правила, одно из которых рекурсивное. Попробуем получить левосторонний вывод какой-нибудь цепочки в этой грамматике: - \begin{align*} - & \boldsymbol{_2S_2} \xRightarrow{(0)\ } \\ - & {_2a_0}\ \boldsymbol{_0S_3}\ {_3b_2} \xRightarrow{(1)\ } \\ - & {_2a_0}\ {_0a_1}\ \boldsymbol{_1S_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(2)\ } \\ - & {_2a_0}\ {_0a_1}\ {_1a_2}\ \boldsymbol{_2S_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(3)\ } \\ - & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ \boldsymbol{_0S_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(4)\ } \\ - & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ \boldsymbol{_1S_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(5)\ } \\ - & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ \boldsymbol{_2S_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(0)\ } \\ - & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ \boldsymbol{_0S_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(1)\ } \\ - & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ \boldsymbol{_1S_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(2)\ } \\ - & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ \boldsymbol{_2S_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(3)\ } \\ - & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ \boldsymbol{_0S_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(4)\ } \\ - & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ \boldsymbol{_1S_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(6)\ } \\ - & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} - \end{align*} - - Мы получили цепочку, которая действительно является путем из вершины 2 в вершину 2 в заданном графе. Таким образом выводятся и любые другие соответствующие пути. - -\end{example} - - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item Постройте дерево вывода цепочки $w=aababb$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ S \}, S \rangle$. -% \item Постройте все левосторонние выводы цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$. -% \item Постройте все правосторонние выводы цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$. -% \item \label{t1}Постройте все деревья вывода цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$, соответствующие левосторонним выводам. -% \item \label{t2}Постройте все деревья вывода цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$, соответствующие правосторонним выводам. -% \item Как связаны между собой леса, полученные в предыдущих двух задачах (\ref{t1} и \ref{t2})? Какие выводы можно сделать из такой связи? -% \item Постройте сжатое представление леса разбора, полученного в задаче~\ref{t1}. -% \item Постройте сжатое представление леса разбора, полученного в задаче~\ref{t2}. -% \item \label{t3}Предъявите контекстно-свободную грамматику существенно неоднозначного языка. -% Возьмите цепочку длины болше пяти, при надлежащую этому языку, и постройте все деревья вывода этой цепочки в предъявленной грамматике. -% \item Постройте сжатое представление леса, полученного в задаче~\ref{t3}. -%\end{enumerate} diff --git a/tex/TensorProduct.tex b/tex/TensorProduct.tex deleted file mode 100644 index 28a2ef8..0000000 --- a/tex/TensorProduct.tex +++ /dev/null @@ -1,1366 +0,0 @@ -\chapter{КС достижимость через тензорное произведение} - -Предыдущий подход позволяет выразить задачу поиска путей с ограничениями в терминах формальных языков через набор матричных операций. -Это позволяет использовать высокопроизводительные библиотеки, массовопараллельные архитектуры и другие готовые решения для линейной алгебры. -Однако, такой подход требует, чтобы грамматика находилась в ослабленной нормальной форме Хомского, что приводит к её разрастанию. -Можно ли как-то избежать этого? - -В данном разделе мы предложим альтернативное сведение задачи поиска путей к матричным операциям. -В результате мы сможем избежать преобразования грамматики в ОНФХ, однако, матрицы, с которыми нам предётся работать, будут существенно б\'{о}льшего размера. - -В основе подхода лежит использование рекурсивных сетей или рекурсивных автоматов в качестве представления контекстно-свободных грамматик и использование тензорного (прямого) произведения для нахождения пересечения автоматов. - - - -\section{Тензорное произведение} -\label{section2} - -Теперь перейдём к графам. -Сперва дадим классическое определение тензорного произведения двух неориентированных графов. - -\begin{definition} -Пусть даны два графа: $\mathcal{G}_1 = \langle V_1, E_1\rangle$ и $\mathcal{G}_2 = \langle V_2, E_2\rangle$. -Тензорным произведением этих графов будем называть граф $\mathcal{G}_3 = \langle V_3, E_3\rangle$, где $V_3 = V_1 \times V_2$, $E_3 = \{ ((v_1,v_2),(u_1,u_2)) \mid (v_1,u_1) \in E_1 \text{ и } (v_2,u_2) \in E_2 \}$. -\end{definition} - -Иными словами, тензорным произведением двух графов является граф, такой что: -\begin{enumerate} - \item множество вершин --- это прямое произведение множеств вершин исходных графов; - \item ребро между вершинами $v=(v_1,v_2)$ и $u=(u_1,u_2)$ существует тогда и только тогда, когда существуют рёбра между парами вершин $v_1$, $u_1$ и $v_2$, $u_2$ в соответствующих графах. -\end{enumerate} - -Для того, чтобы построить тензорное произведение ориентированных графов, необходимо в предыдущем определении, в условии существования ребра в результирующем графе, дополнительно потребовать, чтобы направления рёбер совпадали. -Данное требование получается естественным образом, если считать, что пары вершин, задающие ребро, упорядочены, поэтому формальное определение отличаться не будет. - -Осталось добавить метки к рёбрам. -Это приведёт к логичному усилению требования к существованию ребра: метки рёбер в исходных графах должны совпадать. -Таким образом, мы получаем следующее определение тензорного произведения ориентированных графов с метками на рёбрах. - -\begin{definition} -Пусть даны два ориентированных графа с метками на рёбрах: $\mathcal{G}_1 = \langle V_1, E_1, L_1 \rangle$ и $\mathcal{G}_2 = \langle V_2, E_2, L_2 \rangle$. -Тензорным произведением этих графов будем называть граф $\mathcal{G}_3 = \langle V_3, E_3, L_3\rangle$, где $V_3 = V_1 \times V_2$, $E_3 = \{ ((v_1,v_2),l,(u_1,u_2)) \mid (v_1,l,u_1) \in E_1 \text{ и } (v_2,l,u_2) \in E_2 \}$, $L_3=L_1 \cap L_2$. -\end{definition} - -Нетрудно заметить, что матрица смежности графа $\mathcal{G}_3$ равна тензорному произведению матриц смежностей исходных графов $\mathcal{G}_1$ и $\mathcal{G}_2$. - -\begin{example} -Рассмотрим пример. -В качестве одного из графов возьмём рекурсивный автомат, построенный ранее (изображение~\ref{input1}). -Его матрица смежности выглядит следующим образом. -\[ M_1 = -\begin{pmatrix} -. & [a] & . & . \\ -. & . & [S] & [b] \\ -. & . & . & [b] \\ -. & . & . & . -\end{pmatrix} -\] - -\begin{align} -\label{input2} - \input{figures/graph/graph0.tex} -\end{align} - -Второй граф представлен на изображении~\ref{input2}. -Его матрица смежности имеет следующий вид. -\[ M_2 = -\begin{pmatrix} -. & [a] & . & . \\ -. & . & [a] & . \\ -[a] & . & . & [b] \\ -. & . & [b] & . -\end{pmatrix} -\] - -Теперь вычислим $M_1 \otimes M_2$. -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -M_3 &= M_1 \otimes M_2 = -\begin{pmatrix} -. & [a] & . & . \\ -. & . & [S] & [b] \\ -. & . & . & [b] \\ -. & . & . & . -\end{pmatrix} -\otimes -\begin{pmatrix} -. & [a] & . & . \\ -. & . & [a] & . \\ -[a] & . & . & [b] \\ -. & . & [b] & . -\end{pmatrix} -=\notag\\ -&= -\label{eq:graph_tm} -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -\end{example} - -\section{Алгоритм} - -Идея алгоритма основана на обобщении пересечения двух конечных автоматов до пересечения рекурсивного автомата, построенного по грамматике, со входным графом. - -Пересечение двух конечных автоматов --- тензорное произведение соответствующих графов. -Пересечение языков коммутативно, тензорное произведение нет, но, как было сказано в замечании~\ref{note:KronIsNotCommutative}, существует решение этой проблемы. - -Будем рассматривать два конечных автомата: одни получен из входного графа, второй из грамматики. -Можно найти их пересечение, вычислив тензорное произведение матриц смежности соответствующих графов. -Однако, одной такой итерации не достаточно для решения исходной задачи. За первую итерацию мы найдём только те пути, которые выводятся в грамматике за одни шаг. После этого необходимо добавить соответствующие рёбра во входной граф и повторить операцию: так мы найдём пути, выводимые за два шага. Данные действия надо повторять до тех пор, пока не перестанут находиться новые пары достижимых вершин. -Псевдокод, описывающий данные действия, представлен в листинге~\ref{lst:algo1}. - -\begin{algorithm} - \floatname{algorithm}{Listing} -\begin{algorithmic}[1] -\caption{Поиск путей через тензорное произведение} -\label{lst:algo1} -\Function{contextFreePathQueryingTP}{G, $\mathcal{G}$} - \State{$R \gets$ рекурсивный автомат для $G$} - \State{$N \gets$ нетерминальный алфавит для $R$} - \State{$S \gets$ стартовые состояния для $R$} - \State{$F \gets$ конечные состояния для $R$} - \State{$M_1 \gets$ матрица смежности $R$} - \State{$M_2 \gets$ матрица смежности $\mathcal{G}$} - \For{$N_i \in N$} - \If{$N_i \xrightarrow{*} \varepsilon$} - \State{for all $j \in \mathcal{G}.V: M_2[j,j] \gets M_2[j,j] \cup \{N_i\}$} - \Comment{Добавим петли для нетерминалов, выводящих $\varepsilon$} - \EndIf - \EndFor - \While{матрица $M_2$ изменяется} - \State{$M_3 \gets M_1 \otimes M_2$} - \Comment{Пересечение графов} - \State{$tC_3 \gets \textit{transitiveClosure}(M_3)$} - \State{$n \gets$ количество строк и столбцов матрицы $M_3$} - \Comment{размер матрицы $M_3$ = $n \times n$} - \For{$i \in 0..n$} - \For{$j \in 0..n$} - \If{$tC_3[i,j]$} - \State{$s \gets$ стартовая вершина ребра $tC_3[i,j]$} - \State{$f \gets$ конечная вершина ребра $tC_3[i,j]$} - \If{$s \in S$ and $f \in F$ } - \State{$x, y \gets$ $getCoordinates(i,j)$} - \State{$M_2[x,y] \gets M_2[x,y] \cup \{getNonterminals(s,f)\}$} - \EndIf - \EndIf - \EndFor - \EndFor - \EndWhile -\State \Return $M_2$ -\EndFunction -\end{algorithmic} -\end{algorithm} - - -Алгоритм исполняется до тех пор, пока матрица смежности $M_2$ изменяется. -На каждой итерации цикла алгоритм последовательно проделывает следующие команды: пересечение двух автоматов через тензорное произведение, транзитивное замыкание результата тензорного произведения и итерация по всем ячейкам получившейся после транзитивного замыкания матрицы, что необходимо для поиска новых пар достижимых вершин. -Во время итерации по ячейкам матрицы транзитивного замыкания алгоритм сначала проверяет наличие ребра в данной ячейке, а затем --- принадлежность стартовой и конечной вершин ребра к стартовому и конечному состоянию входного рекурсивного автомата. -При удовлетворении этих условий алгоритм добавляет нетерминал (или нетерминалы), соответствующие стартовой и конечной вершинам ребра, в ячейку матрицы $M_2$, полученной при помощи функции $getCoordinates(i,j)$. - -Представленный алгоритм не требует преобразования грамматики в ОНФХ, более того, рекурсивный автомат может быть минимизирован. Однако, результатом тензорного рпоизведения является матрица существенно б\'{о}льшего размера, чем в алгоритме, основанном на матричном рпоизведении. -Кроме этого, необходимо искать транзитивное замыкание этой матрицы. - -Ещё одним важным свойством представленного алгоритма является его оптимальность при обработке регулярных запросов. -Так как по контекстно свободной грамматике мы не можем определить, задаёт ли она регулярный язык, то при добавлении в язык запросов возможности задавать контекстно-свободные ограничения, возникает проблема: мы не можем в общем случае отличить регулярный запрос от контекстно-свободного. Следовательно, мы вынуждены применять наиболее общий механизм выполнения заросов, что может приводить к существенным накладным расходам при выполнении регулярного запроса. -Данный же алгоритм не выполнит лишних действий, так как сразу выполнит классическое пересечение двух автоматов и получит результат. - -\section{Примеры} - -Рассмотрим подробно ряд примеров работы описанного алгоритма. -Будем для каждой итерации внешнего цикла выписывать результаты основных операций: тензорного произведения, транзитивного замыкания, обновления матрицы смежности входного графа. -Новые, по сравнению с предыдущим состоянием, элементы матриц будем выделять. - -\begin{example} -\label{algorithm_example} -Теоретически худший случай. -Такой же как и для матричного. - -\textbf{Итерация 1 (конец).} Начало в разделе~\ref{section2}, где мы вычислили тензорное произведение матриц смежности. -Теперь нам осталось только вычислить транзитивное замыкание полученной матрицы: - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -tc(M_3) = -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & .\\ -. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & \bfgray{[ab]} \\ -. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right). -\end{scaledalign} - -Мы видим, что в результате транзитивного замыкания появилось новое ребро с меткой $ab$ из вершины $(0,1)$ в вершину $(3,3)$. -Так как вершина 0 является стартовой в рекурсивном автомате, а 3 является финальной, то слово вдоль пути из вершины 1 в вершину 3 во входном графе выводимо из нетерминала $S$. -Это означает, что в графе должно быть добавлено ребро из $0$ в $3$ с меткой $S$, после чего граф будет выглядеть следующим образом: - -\begin{center} - \input{figures/tensor/graph0.tex} -\end{center} - -Матрица смежности обновлённого графа: -\[ M_2 = -\begin{pmatrix} -. & [a] & . & . \\ -. & . & [a] & \textbf{[S]} \\ -[a] & . & . & [b] \\ -. & . & [b] & . -\end{pmatrix} -\] - -Итерация закончена. -Возвращаемся к началу цикла и вновь вычисляем тензорное произведение. - -\textbf{Итерация 2.} -Вычисляем тензорное произведение матриц смежности. - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -M_3 &= M_1 \otimes M_2 = -\begin{pmatrix} -. & [a] & . & . \\ -. & . & [S] & [b] \\ -. & . & . & [b] \\ -. & . & . & . -\end{pmatrix} -\otimes -\begin{pmatrix} -. & [a] & . & . \\ -. & . & [a] & [S] \\ -[a] & . & . & [b] \\ -. & . & [b] & . -\end{pmatrix} -=\notag\\ -&= -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & \bfgray{[S]} & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Вычисляем транзитивное замыкание полученной матрицы: - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -tc(M_3) = -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & . & \bfgray{[aS]} & . & . & \bfgray{[aSb]} & . \\ -. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & [ab] \\ -. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & \bfgray{[Sb]} & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -В транзитивном замыкании появилось три новых ребра, однако только одно из них соединяет вершины, соответствующие стартовому и конечному состоянию входного рекурсивного автомата. -Таким образом только это ребро должно быть добавлено во входной граф. -В итоге, обновлённый граф: -\begin{center} -\input{figures/tensor/graph1.tex} -\end{center} - -И его матрица смежности: -\[ M_2 = -\begin{pmatrix} -. & [a] & [S] & . \\ -. & . & [a] & [S] \\ -[a] & . & . & [b] \\ -. & . & [b] & . -\end{pmatrix} -\] -\textbf{Итерация 3.} -Снова начинаем с тензорного произведения. - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -M_3 &= M_1 \otimes M_2 = -\begin{pmatrix} -. & [a] & . & . \\ -. & . & [S] & [b] \\ -. & . & . & [b] \\ -. & . & . & . -\end{pmatrix} -\otimes -\begin{pmatrix} -. & [a] & [S] & . \\ -. & . & [a] & [S] \\ -[a] & . & . & [b] \\ -. & . & [b] & . -\end{pmatrix} -=\notag\\ -&= -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & \bfgray{[S]} & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Затем вычисляем транзитивное замыкание: - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -tc(M_3) = -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & . & [aS] & . & . & [aSb] & . \\ -. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & [ab] \\ -. & . & . & . & [a] & . & . & . & . & . & \bfgray{[aS]} & . & . & . & . & \bfgray{[aSb]} \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & \bfgray{[Sb]} \\ -. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & [Sb] & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -И наконец обновляем граф: -\begin{center} -\input{figures/tensor/graph2.tex} -\end{center} - -Матрица смежности обновлённого графа: -\[ M_2 = -\begin{pmatrix} -. & [a] & [S] & . \\ -. & . & [a] & [S] \\ -[a] & . & . & [b, \textbf{S}] \\ -. & . & [b] & . -\end{pmatrix} -\] -Уже можно заметить закономерность: на каждой итерации мы добавляем ровно одно новое ребро во входной граф, ровно как и в алгоритме, основанном на матричном произведении, и как в алгоритме Хеллингса. -То есть находим ровно одну новую пару вершин, между которыми существует интересующий нас путь. -Попробуйте спрогнозировать, сколько итераций нам ещё осталось сделать. - -\textbf{Итерауия 4}. -Продолжаем. Вычисляем тензорное произведение. - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -M_3 &= M_1 \otimes M_2 = -\begin{pmatrix} -. & [a] & . & . \\ -. & . & [S] & [b] \\ -. & . & . & [b] \\ -. & . & . & . -\end{pmatrix} -\otimes -\begin{pmatrix} -. & [a] & [S] & . \\ -. & . & [a] & [S] \\ -[a] & . & . & [b,S] \\ -. & . & [b] & . -\end{pmatrix} -=\notag\\ -&= -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & \bfgray{[S]} & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Затем транзитивное замыкание: - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -tc(M_3) = -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & . & [aS] & . & . & [aSb] & . \\ -. & . & . & . & . & . & [a] & . & . & . & . & \bfgray{[aS]} & . & . & \bfgray{[aSb]} & [ab] \\ -. & . & . & . & [a] & . & . & . & . & . & [aS] & . & . & . & . & [aSb] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & [Sb] \\ -. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & [Sb] & . \\ -. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & \bfgray{[Sb]} & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -И снова обновляем граф, так как в транзитивном замыкании появился один (и снова ровно один) новый элемент, соответствующий принимающему пути в автомате. -\begin{center} -\input{figures/tensor/graph3.tex} -\end{center} - - -Матрица смежности обновлённого графа: -\[ M_2 = -\begin{pmatrix} -. & [a] & [S] & . \\ -. & . & [a, \textbf{S}] & [S] \\ -[a] & . & . & [b,S] \\ -. & . & [b] & . -\end{pmatrix} -\] -\textbf{Итерация 5.} -Приступаем к выполнению следующей итерации основного цикла. -Вычисляем тензорное произведение. - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -M_3 &= M_1 \otimes M_2 = -\begin{pmatrix} -. & [a] & . & . \\ -. & . & [S] & [b] \\ -. & . & . & [b] \\ -. & . & . & . -\end{pmatrix} -\otimes -\begin{pmatrix} -. & [a] & [S] & . \\ -. & . & [a,S] & [S] \\ -[a] & . & . & [b,S] \\ -. & . & [b] & . -\end{pmatrix} -=\notag\\ -&= -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & \bfgray{[S]} & [S] & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Затем вычисляем транзитивное замыкание: - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -tc(M_3) = -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & \bfgray{[aS]} & [aS] & . & . & [aSb] & \bfgray{[aSb]} \\ -. & . & . & . & . & . & [a] & . & . & . & . & [aS] & . & . & [aSb] & [ab] \\ -. & . & . & . & [a] & . & . & . & . & . & [aS] & . & . & . & . & [aSb] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & [Sb] \\ -. & . & . & . & . & . & . & . & . & . & [S] & [S] & . & . & [Sb] & \bfgray{[Sb]} \\ -. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & [Sb] & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Обновляем граф: -\begin{center} - \input{figures/tensor/graph4.tex} -\end{center} - - -Матрица смежности обновлённого графа: -\[ M_2 = -\begin{pmatrix} -. & [a] & [S] & \textbf{[S]} \\ -. & . & [a, S] & [S] \\ -[a] & . & . & [b,S] \\ -. & . & [b] & . -\end{pmatrix} -\] -\textbf{Итерация 6.} -И наконец последняя содержательная итерация основного цикла. - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -M_3 &= M_1 \otimes M_2 = -\begin{pmatrix} -. & [a] & . & . \\ -. & . & [S] & [b] \\ -. & . & . & [b] \\ -. & . & . & . -\end{pmatrix} -\otimes -\begin{pmatrix} -. & [a] & [S] & [S] \\ -. & . & [a,S] & [S] \\ -[a] & . & . & [b,S] \\ -. & . & [b] & . -\end{pmatrix} -=\\ -&= -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & [S] & \bfgray{[S]} & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & [S] & [S] & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Транзитивное замыкание: - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -tc(M_3) = -\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } -. & . & . & . & . & [a] & . & . & . & . & [aS] & [aS] & . & . & [aSb] & [aSb] \\ -. & . & . & . & . & . & [a] & . & . & . & . & [aS] & . & . & [aSb] & [ab] \\ -. & . & . & . & [a] & . & . & . & . & . & [aS] & \bfgray{[aS]} & . & . & \bfgray{[aSb]} & [aSb] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & [S] & \bfgray{[S]} & . & . & \bfgray{[Sb]} & [Sb] \\ -. & . & . & . & . & . & . & . & . & . & [S] & [S] & . & . & [Sb] & [Sb] \\ -. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & [Sb] & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Обновлённый граф: -\begin{center} -\input{figures/tensor/graph5.tex} -\end{center} - - -И матрица смежности: -\[ M_2 = -\begin{pmatrix} -. & [a] & [S] & [S] \\ -. & . & [a, S] & [S] \\ -[a] & . & \textbf{[S]} & [b,S] \\ -. & . & [b] & . -\end{pmatrix} -\] -Следующая итерация не приведёт к изменению графа. -Читатель может убедиться в этом самостоятельно. -Соответственно, алгоритм можно завершать. -Нам потребовалось семь итераций (шесть содержательных и одна проверочная), на каждой из которых вычисляются тензорное произведение двух матриц смежности и транзитивное замыкание результата. - -Матрица смежности получилась такая же, как и раньше, ответ правильный. -Мы видим, что количество итераций внешнего цикла такое же как и у алгоритма CYK (пример~\ref{CYK_algorithm_ex}). - -\end{example} - - -\begin{example} - -В данном примере мы увидим, как структура грамматики и, соответственно, рекурсивного автомата, влияет на процесс вычислений. - -Интуитивно понятно, что чем меньше состояний в рекурсивной сети, тем лучше. -То есть желательно получить как можно более компактное описание контекстно-свободного языка. - -Для примера возьмём в качестве КС языка язык Дика на одном типе скобок и опишем его двумя различными грамматиками. -Первая грамматика классическая: -\[ -G_1 = \langle \{a,\ b\}, \{ S \}, \{S \to a \ S \ b \ S \mid \varepsilon \} \rangle -\] -Во второй грамматике мы будем использовать конструкции регулярных выражений в правой части правил. -То есть вторая грамматика находится в EBNF (Расширенная форма Бэкуса-Наура~\cite{Hemerik2009, Wirth1977}). -\[ -G_2 = \langle \{a, \ b\}, \{S\}, \{S \to (a \ S \ b)^{*}\} \rangle -\] -Построим рекурсивные автоматы $N_1$ и $N_2$ и их матрицы смежности для этих грамматик. - -Рекурсивный автомат $N_1$ для грамматики $G_1$: -\begin{center} -\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] - \node[state, initial, accepting] (q_0) {$0$}; - \node[state] (q_1) [right=of q_0] {$1$}; - \node[state] (q_2) [right=of q_1] {$2$}; - \node[state] (q_3) [right=of q_2] {$3$}; - \node[state, accepting] (q_4) [right=of q_3] {$4$}; - \path[->] - (q_0) edge node {a} (q_1) - (q_1) edge node {S} (q_2) - (q_2) edge node {b} (q_3) - (q_3) edge node {S} (q_4); -\end{tikzpicture} -\end{center} - -Матрица смежности $N_1$: -\[ -M_1^1 = -\begin{pmatrix} -. & [a] & . & . & . \\ -. & . & [S] & . & . \\ -. & . & . & [b] & . \\ -. & . & . & . & [S] \\ -. & . & . & . & . -\end{pmatrix} -\] -Рекурсивный автомат $N_2$ для грамматики $G_2$: -\begin{center} - \input{figures/tensor/recursive.tex} -\end{center} - -Матрица смежности $N_2$: -\[ -M_1^2 = -\begin{pmatrix} -. & [a] & . \\ -. & . & [S] \\ -[b] & . & . -\end{pmatrix} -\] -Первое очевидное наблюдение --- количество состояний в $N_2$ меньше, чем в $N_1$. -Это значит, что матрица смежности, а значит, и результат тензорного произведения будут меньше, следовательно, вычисления будут производиться быстрее. - -Выполним пошагово алгоритм для двух заданных рекурсивных сетей на линейном входе: -\begin{center} -\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] - \node[state] (q_0) {$0$}; - \node[state] (q_1) [right=of q_0] {$1$}; - \node[state] (q_2) [right=of q_1] {$2$}; - \node[state] (q_3) [right=of q_2] {$3$}; - \node[state] (q_4) [right=of q_3] {$4$}; - \node[state] (q_5) [right=of q_4] {$5$}; - \node[state] (q_6) [right=of q_5] {$6$}; - \path[->] - (q_0) edge node {a} (q_1) - (q_1) edge node {b} (q_2) - (q_2) edge node {a} (q_3) - (q_3) edge node {b} (q_4) - (q_4) edge node {a} (q_5) - (q_5) edge node {b} (q_6); -\end{tikzpicture} -\end{center} - - -Сразу дополним матрицу смежности нетерминалами, выводящими пустую строку, и получим следующую матрицу: -\begin{scaledalign}{\footnotesize}{0.5pt}{0.9}{\notag} -M_2 = -\begin{pmatrix} -[S] & [a] & . & . & . & . & . \\ -. & [S] & [b] & . & . & . & . \\ -. & . & [S] & [a] & . & . & . \\ -. & . & . & [S] & [b] & . & . \\ -. & . & . & . & [S] & [a] & . \\ -. & . & . & . & . & [S] & [b] \\ -. & . & . & . & . & . & [S] -\end{pmatrix} -\end{scaledalign} - -Сперва запустим алгоритм на данном входе и $N_2$. -Первый шаг первой итерации --- вычисление тензорного произведения $M_1^2 \otimes M_2$. - -\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} -M_3 &= M_1^2 \otimes M_2 = -\begin{pmatrix} -. & [a] & . \\ -. & . & [S] \\ -[b] & . & . -\end{pmatrix} -\otimes -\begin{pmatrix} -[S] & [a] & . & . & . & . & . \\ -. & [S] & [b] & . & . & . & . \\ -. & . & [S] & [a] & . & . & . \\ -. & . & . & [S] & [b] & . & . \\ -. & . & . & . & [S] & [a] & . \\ -. & . & . & . & . & [S] & [b] \\ -. & . & . & . & . & . & [S] -\end{pmatrix} -=\notag\\ -&= -\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c } -. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - - -\newcommand{\tinybf}[1]{\cellcolor{lightgray}\textbf{\tiny{[#1]}}} -\newcommand{\tntm}[1]{\text{\tiny{#1}}} - -Опустим промежуточные шаги вычисления транзитивного замыкания $M_3$ и сразу представим конечный результат: -\begin{scaledalign}{\footnotesize}{0.5pt}{0.5}{\notag} -&tc(M_3)= -\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c } -. & . & \tinybf{aSb} & . & \tinybf{aSbaSb} & . & \tinybf{aSbaSbaSb} & . & [a] & . & \tinybf{aSba} & . & \tinybf{aSbaSba} & . & . & \tinybf{aS} & . & \tinybf{aSbaS} & . & \tinybf{aSbaSbaS} & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & \tinybf{aSb} & . & \tinybf{aSbaSb} & . & . & . & [a] & . & \tinybf{aSba} & . & . & . & . & \tinybf{aS} & . & \tinybf{aSbaS} & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & \tinybf{aSb} & . & . & . & . & . & [a] & . & . & . & . & . & . & \tinybf{aS} & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -В результате вычисления транзитивного замыкания появилось большое количество новых рёбер, однако нас будут интересовать только те, информация о которых храниться в левом верхнем блоке. -Остальные рёбра не соответствуют принимающим путям в рекурсивном автомате (убедитесь в этом самостоятельно). - -После добавления соответствующих рёбер, мы получим следующий граф: -\begin{center} -\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] - \node[state] (q_0) {$0$}; - \node[state] (q_1) [right=of q_0] {$1$}; - \node[state] (q_2) [right=of q_1] {$2$}; - \node[state] (q_3) [right=of q_2] {$3$}; - \node[state] (q_4) [right=of q_3] {$4$}; - \node[state] (q_5) [right=of q_4] {$5$}; - \node[state] (q_6) [right=of q_5] {$6$}; - \path[->] - (q_0) edge node {a} (q_1) - (q_0) edge[bend left, above] node {\textbf{S}} (q_2) - (q_0) edge[bend right, above] node {\textbf{S}} (q_4) - (q_0) edge[bend right, above] node {\textbf{S}} (q_6) - (q_1) edge node {b} (q_2) - (q_2) edge node {a} (q_3) - (q_2) edge[bend left, above] node {\textbf{S}} (q_4) - (q_2) edge[bend right, above] node {\textbf{S}} (q_6) - (q_3) edge node {b} (q_4) - (q_4) edge node {a} (q_5) - (q_4) edge[bend left, above] node {\textbf{S}} (q_6) - (q_5) edge node {b} (q_6); -\end{tikzpicture} -\end{center} - - -Его матрица смежности: - -\begin{scaledalign}{\footnotesize}{0.5pt}{0.9}{\notag} -M_2 = -\begin{pmatrix} -[S] & [a] & \bfgray{[S]} & . & \bfgray{[S]} & . & \bfgray{[S]} \\ -. & [S] & [b] & . & . & . & . \\ -. & . & [S] & [a] & \bfgray{[S]} & . & \bfgray{[S]} \\ -. & . & . & [S] & [b] & . & . \\ -. & . & . & . & [S] & [a] & \bfgray{[S]} \\ -. & . & . & . & . & [S] & [b] \\ -. & . & . & . & . & . & [S] -\end{pmatrix} -\end{scaledalign} - -Таким образом видно, что для выбранных входных данных алгоритму достаточно двух итераций основного цикла: первая содержательная, вторая, как обычно, проверочная. -Читателю предлагается самостоятельно выяснить, сколько умножений матриц потребуется, чтобы вычислить транзитивное замыкание на первой итерации. - -Теперь запустим алгоритм на второй грамматике и том же входе. - -\begin{scaledalign}{\footnotesize}{0.5pt}{0.8}{\notag} -&M_3 = M_1^1 \otimes M_2 = -\begin{pmatrix} -. & [a] & . & . & . \\ -. & . & [S] & . & . \\ -. & . & . & [b] & . \\ -. & . & . & . & [S] \\ -. & . & . & . & . -\end{pmatrix} -\otimes -\begin{pmatrix} -[S] & [a] & . & . & . & . & . \\ -. & [S] & [b] & . & . & . & . \\ -. & . & [S] & [a] & . & . & . \\ -. & . & . & [S] & [b] & . & . \\ -. & . & . & . & [S] & [a] & . \\ -. & . & . & . & . & [S] & [b] \\ -. & . & . & . & . & . & [S] -\end{pmatrix} -=\notag\\ -&= -\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} -. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Уже сейчас можно заметить, что размер матриц, с которыми нам придётся работать, существенно увеличился, по сравнению с предыдущим вариантом. -Это, конечно, закономерно, ведь в рекурсивном автомате для предыдущего варианта меньше состояний, а значит и матрица смежности имеет меньший размер. - -Транзитивное замыкание: -\begin{scaledalign}{\footnotesize}{0.3pt}{0.5}{\notag} -&tc(M_3)= -\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} -. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tinybf{aS} & . & . & . & . & . & . & . & \tinybf{aSb} & . & . & . & . & . & . & \tinybf{aSbS} & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tinybf{aS} & . & . & . & . & . & . & . & \tinybf{aSb} & . & . & . & . & . & . & \tinybf{aSbS} & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tinybf{aS} & . & . & . & . & . & . & . & \tinybf{aSb} & . & . & . & . & . & . & \tinybf{aSbS} \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Обновлённый граф: -\begin{center} -\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] - \node[state] (q_0) {$0$}; - \node[state] (q_1) [right=of q_0] {$1$}; - \node[state] (q_2) [right=of q_1] {$2$}; - \node[state] (q_3) [right=of q_2] {$3$}; - \node[state] (q_4) [right=of q_3] {$4$}; - \node[state] (q_5) [right=of q_4] {$5$}; - \node[state] (q_6) [right=of q_5] {$6$}; - \path[->] - (q_0) edge node {a} (q_1) - (q_0) edge[bend left, above] node {\textbf{S}} (q_2) - (q_1) edge node {b} (q_2) - (q_2) edge node {a} (q_3) - (q_2) edge[bend left, above] node {\textbf{S}} (q_4) - (q_3) edge node {b} (q_4) - (q_4) edge node {a} (q_5) - (q_4) edge[bend left, above] node {\textbf{S}} (q_6) - (q_5) edge node {b} (q_6); -\end{tikzpicture} -\end{center} - - -Его матрица смежности: - -\begin{scaledalign}{\footnotesize}{0.5pt}{0.9}{\notag} -M_2 = -\begin{pmatrix} -[S] & [a] & \bfgray{[S]} & . & . & . & . \\ -. & [S] & [b] & . & . & . & . \\ -. & . & [S] & [a] & \bfgray{[S]} & . & . \\ -. & . & . & [S] & [b] & . & . \\ -. & . & . & . & [S] & [a] & \bfgray{[S]} \\ -. & . & . & . & . & [S] & [b] \\ -. & . & . & . & . & . & [S] -\end{pmatrix} -\end{scaledalign} - -Потребуется ещё одна итерация. - -\begin{scaledalign}{\footnotesize}{0.5pt}{0.8}{\notag} -&M_3 = M_1^1 \otimes M_2 = -\begin{pmatrix} -. & [a] & . & . & . \\ -. & . & [S] & . & . \\ -. & . & . & [b] & . \\ -. & . & . & . & [S] \\ -. & . & . & . & . -\end{pmatrix} -\otimes -\begin{pmatrix} -[S] & [a] & [S] & . & . & . & . \\ -. & [S] & [b] & . & . & . & . \\ -. & . & [S] & [a] & [S] & . & . \\ -. & . & . & [S] & [b] & . & . \\ -. & . & . & . & [S] & [a] & [S] \\ -. & . & . & . & . & [S] & [b] \\ -. & . & . & . & . & . & [S] -\end{pmatrix} -=\notag\\ -&= -\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} -. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Транзитивное замыкание: -\begin{scaledalign}{\footnotesize}{0.3pt}{0.5}{\notag} -&tc(M_3)= -\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} -. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & \tinybf{aS} & . & . & . & . & . & \tntm{[aSb]} & . & \tinybf{aSb} & . & . & . & . & \tntm{[aSbS]} & . & \tinybf{aSbS} & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & \tinybf{aS} & . & . & . & . & . & \tntm{[aSb]} & . & \tinybf{aSb} & . & . & . & . & \tntm{[aSbS]} & . & \tinybf{aSbS} \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & . & . & . & . & . & . & \tntm{[aSb]} & . & . & . & . & . & . & \tntm{[aSbS]} \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Обновлённый граф: -\begin{center} -\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] - \node[state] (q_0) {$0$}; - \node[state] (q_1) [right=of q_0] {$1$}; - \node[state] (q_2) [right=of q_1] {$2$}; - \node[state] (q_3) [right=of q_2] {$3$}; - \node[state] (q_4) [right=of q_3] {$4$}; - \node[state] (q_5) [right=of q_4] {$5$}; - \node[state] (q_6) [right=of q_5] {$6$}; - \path[->] - (q_0) edge node {a} (q_1) - (q_0) edge[bend left, above] node {S} (q_2) - (q_0) edge[bend right, above] node {\textbf{S}} (q_4) - (q_1) edge node {b} (q_2) - (q_2) edge node {a} (q_3) - (q_2) edge[bend left, above] node {S} (q_4) - (q_2) edge[bend right, above] node {\textbf{S}} (q_6) - (q_3) edge node {b} (q_4) - (q_4) edge node {a} (q_5) - (q_4) edge[bend left, above] node {S} (q_6) - (q_5) edge node {b} (q_6); -\end{tikzpicture} -\end{center} - -На этом шаге мы смогли ``склеить'' из подстрок, выводимых из $S$, более длинные пути. -Однако, согласно правилам грамматики, мы смогли ``склеить'' только две подстроки в единое целое. - -Матрица смежности обновлённого графа: - -\begin{scaledalign}{\footnotesize}{0.5pt}{0.9}{\notag} -M_2 = -\begin{pmatrix} -[S] & [a] & [S] & . & \bfgray{[S]} & . & \\ -. & [S] & [b] & . & . & . & . \\ -. & . & [S] & [a] & [S] & . & \bfgray{[S]} \\ -. & . & . & [S] & [b] & . & . \\ -. & . & . & . & [S] & [a] & [S] \\ -. & . & . & . & . & [S] & [b] \\ -. & . & . & . & . & . & [S] -\end{pmatrix} -\end{scaledalign} - -И, наконец, последняя содержательная итерация. - -\begin{scaledalign}{\footnotesize}{0.5pt}{0.8}{\notag} -&M_3 = M_1^1 \otimes M_2 = -\begin{pmatrix} -. & [a] & . & . & . \\ -. & . & [S] & . & . \\ -. & . & . & [b] & . \\ -. & . & . & . & [S] \\ -. & . & . & . & . -\end{pmatrix} -\otimes -\begin{pmatrix} -[S] & [a] & [S] & . & [S] & . & . \\ -. & [S] & [b] & . & . & . & . \\ -. & . & [S] & [a] & [S] & . & [S] \\ -. & . & . & [S] & [b] & . & . \\ -. & . & . & . & [S] & [a] & [S] \\ -. & . & . & . & . & [S] & [b] \\ -. & . & . & . & . & . & [S] -\end{pmatrix} -=\notag\\ -&= -\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} -. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & \bfgray{[S]} & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & \bfgray{[S]} & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & \bfgray{[S]} & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & \bfgray{[S]} \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - -Транзитивное замыкание: -\begin{scaledalign}{\footnotesize}{0.3pt}{0.5}{\notag} -&tc(M_3)= -\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} -. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & \tntm{[aS]} & . & \tinybf{aS} & . & . & . & \tntm{[aSb]} & . & \tntm{[aSb]} & . & \tinybf{aSb} & . & . & \tntm{[aSbS]} & . & \tntm{[aSbS]} & . & \tinybf{aSbS} \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & \tntm{[aS]} & . & . & . & . & . & \tntm{[aSb]} & . & \tntm{[aSb]} & . & . & . & . & \tntm{[aSbS]} & . & \tntm{[aSbS]} \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & . & . & . & . & . & . & \tntm{[aSb]} & . & . & . & . & . & . & \tntm{[aSbS]} \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & [S] & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & [S] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ -\hline -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . -\end{array}\right) -\end{scaledalign} - - -В конечном итоге мы получаем такой же результат, как и при первом запуске. -Однако нам потребовалось выполнить существенно больше итераций внешнего цикла, а именно четыре (три содержательных и одна проверочная). -При этом, в ходе работы нам пришлось оперировать существенно б\'{о}льшими матрицами: $35 \times 35$ против $21 \times 21$. - -Таким образом, видно, что минимизация представления запроса, в частности, минимизация рекурсивного автомата как конечного автомата над смешанным алфавитом может улучшить производительность выполнения запросов. -\end{example} - -\section{Особенности реализации} - -Как и алгоритмы, представленные в разделе~\ref{chpt:MatrixBasedAlgos}, представленный здесь алгоритм оперирует разреженными матрицами, поэтому, к нему применимы все те же соображения, что и к алгоритмам, основанным на произведении матриц. Более того, так как результат тензорного произведения является блочной матрицей, то могут оказаться полезными различные форматы для хранения блочно-разреженных матриц. Вместе с этим, в некоторых случаях матрицу смежности рекурсивного автомата удобнее представлять в классическом, плотном, виде, так как для некоторых запросов её размер мал и накладные расходы на представление в разреженном формате и работе с ним будут больше, чем выигрыш от его использования. - - -Также заметим, что блочная структура матриц даёт хорошую основу для распределённого умножения матриц при построении транзитивного замыкания. - -Вместо того, чтобы перезаписывать каждый раз матрицу смежности входного графа $M_2$ можно вычислять только разницу с предыдущим шагом. -Для этого, правда, потребуется хранить в памяти ещё одну матрицу. -Поэтому нужно проверять, что вычислительно дешевле: поддерживать разницу и потом каждый раз поэлементно складывать две матрицы или каждый раз вычислять полностью произведение. - -Заметим, что для решения задачи достижимости нам не нужно накапливать пути вдоль рёбер, как мы это делали в примерах, соответственно, во-первых, можно переопределить тензорное произведение так, чтобы его результатом являлась булева матрица, во-вторых, как следствие первого изменеия, транзитивное замыкание для булевой матрицы можно искать с применением соответствующих оптимизаций. - -%\section{Вопросы и задачи} -% -%\begin{enumerate} -% \item Оценить пространсвенную сложность алгоритма. -% \item Оценить временную сложность алгоритма. -% \item Найти библиотеку для тензорного произведения. Реализовать алгоритм. Можно предпологать, что запросы содержат ограниченное число терминалов и нетерминалов. Провести замеры. Сравнить с матричным. -% \item Реализовать распределённое решение. -%См. блочную структуру -%\end{enumerate} diff --git a/tex/figures/Chomsky.pdf b/tex/figures/Chomsky.pdf deleted file mode 100644 index a0d4d3b70996b90dfdd1823f81da8ab0f23c9192..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14109 zcmdse1yoes+pmG5Lr8ZF9g0jaz#t*r-5@A2beA+rcS|EE0@BhFiqc36NXG!u5(Wt$?yKcd-B?0FfF93@PD)^Z;R(^Jh=m2QX?6#mE8C_(m+_pPJ9^IP+&qiDdk^~@!TrQ<`z`Xai}BBMTI{}? z9BSHNMZdDl%ntcB8~H9Rk+I=sYPJ=<1wXfI-z$yFJwbPtIMkXdee^O14Id?{wHpk1 z%EneG6PJ@b?z~`LjC#S`?tEarA9ws<{vUTpF!JQ?M@cDrJ4~^k?U->vxS(Jt1e4`= z83YW4{*(bFfqy^71_Pv+F=BeJ;o*P+bE_Dcqrfa+D5f|NaY6wN{3^?>h%&V_60>&) z>jMQLU<4oRI)D@pFBA;tfdaR1Brg(da8gzr=o(Pi8H_RDQ)`uWvUhd(t-Gf!o=AW8 zRvqYvlaZaX1EysYkDp>$u#1x`>Ss(G$R&Ytvot}eNsD2GKhRJ^IorEBnV_7(7@ev8 zHckwrKgaoF5kxG3{33JWD!B5cZbIbCB)8s5i>M2 zBWg6RZC_)4KGo&i^O~h4Cz=;w@4_#pw!rQ9M8Xe>VZ8C2lwy0anC_+BH)w$uY5OjW2WT@(3==c9PF9)g`ptaI-E} z!cWF#QPM?73LaVweUb`cqPdYF%g<`#7~(B4J7E^i@+`DjesP1-3^yJ`P8vv6cky6` z=XG+=+mfVmQ4Qo1IVm}ms>m?!_0PTco-PnXbTKeE^|WMNv~at3wxOTKSH$A^@fWL@ zFjmjAjo5;^|6&2Zt-nxS*e?tC>k0TjvjEH*`lkh)tgt85{=dEmoIExD_VBk=?gpKM z;sOu=v@Soy=c*1mX+Ib?=jOAStC>q)MKJgJsOATlM*dUJEw(cq)GG1C3rcVQLBZ=Z(g&g1Q#(>fHy z{TCDXIZOXo1pZpT|7RwEd3gS50w)jD|1V773Ug=Hz(HvIH*Q$cU(^a6$S;Gd} z(v<6#6gGU3m-Jw9>~Tk+FB2L6#a8xP>V#sY7bxSSe0tYz&7tlfa_leb%S_u3EOa+> zIBI>c;?v{d(h+_^z5kkQ|L#Zs^{m+q%tN3%N1*v%^#4;qC;Er{S_1x>y8ko%!!U0x ze;5Gluh*OZv<95MGC;vR5Ptr@;rl_$%Uz?5RK(fuuG^=H-sxUef(lvQ!1oMT&A|lc zL#+cr5*+cNVHC_25>M35i5f!vCH(JE5a^PeFC|hvU#%ZOAjt({1X*elH5KYecv$G} z46?humhCSc^R3SMR{LS!)y#Y|!`ZBFfp7U?19K>QbP`b~!d45l=ardGPQ2cnB(mHedwJs$&l zs09Kjlcak-F(zCPJhCB$Fk}U-ACT8iV6r{YK3MHnSc30F@ z+URNu7(5l72ugTkU*mf?a!Xx=h(zPIWi{&!-KVe8Ej(j+^|;LZrzK<^wH7QKAq7<% z$nf9jw<3?La)B4@?#@qu|)JY@UR}T0DpADLd zL2g}q#>t($U6;ntzOHV!No;<@gR?XjA_suuRj zT%B1g`KFd3izQuHS=;T<97k!rW`2tuKQECCn>IILJZ3CZ`4HLD7h9q~oIDWLN6fG= ztjjcE`?>iRI%*H4VWw5@tt+4ziW|2vQ0e)3Ga-xNqoDYwklju0k4?8t_jyu3NyD_2 z-BKLB)R(L&?sX-OnkCU??7g+_7dqZ8#nZ15*7^8$Ds8k|IV|vSu5YU8b3obDrcZ#- zaeD)wjlPP3`ef0*Qu2C<`Q}*Ps%UTI`UZPx>WqXlmUd;fd&5H#@yPYiKEJu-#AIV- zH;bi>N1u-v^x)#PujzFRZ`)Ud42PP~7aEx>g=;Hkk(H@Plqu5;C0XowFV`3hKUwv6 zSy(}@XfCs&Sj@jvRc$F*?e)gJ@a=1HjI2(maX)1WkFu@)EKUK&X7yGf<`WK!H~AC?zjsnR*rmAy=soS2IDB~{m#)n6%K zE4wj&+p~0ttxI;P?W-|T#8$FUmrY1>>ruY!vS6Bh{R?Tu3BhHUm5jkV6Ws~ea>A}@ zT8TgB)Q0=93MU1JuQ#a~aoB^2Zt~JnLhFy5Wgd^wc}zIuwaGq=G&yYfg?&j$Nf(T# zpXpL}T;C=)@Nj>&oS<#z-6&v?8D{L7vCt&yCZYB&{Z`<;(hG|QW}wz~)3l6i1w#9( z+dWo}Wy>EY-(t}&sB{;IO?s2{ue8YpT zp?Bb`d#9O-TYqP9iQPnFs$V)^7J2#F)R#|d8KDn|HPQuoaugRG=@~zsE0jV!B@KT> z7}0869{gA}fKl_>eHU9n5qRgF=m$wE$?Sv=j2}H$pDLprh_3f+a58AQb)&-5%~f&@ z=R&Il^uc>q^7pdWxQ`l+^3(57OSiEOGS@gCQS~NCtVif74DTBm#ehm)Ost-`eBPB3|3Ff3Q@OdjCr{Rt*XO%JQQmNSvMPZ8glS3e9~qqsrLFysjuAe;(Cy5GJwTDixz2OT~T zI+r3BRqUm{7+D~9ZGMdD1@B`6{cL4YuH6FR5pVdqFM^10a;iXaF|=^y0v(RR#SWfZ z*E-}r^Drvr^M2y@A;>bvTM~#)v*7(`$y#Q$YUvs5G?y>+jwEVS1Kfm8Q2go`U8h<+ z`0^2NaamuMV!mtCdo+5i@w1EpxM&^z*7L;WQIore$LbJ9<`Ar1aK3>LbJ zRv*^VRN6!FI@(AB(25x%y3n3khx>9cd*zDF^P>1AF|iUmHs$K9hk`iILi zbq>|lf}hzXIR~z2hMRx7_CU#0b9v_SZELRY$!nzDlzO=(OSoN6vNxm@k8Iuvv(lG+ z6O8_(QXvE=0;+KvQ+y-r(f&S&pL@}erc~s(?wc$Ra&Wqbmh_cGlg7x zZkgJbZftAwz1*A2pr6&*sTRv`zCCsDCY<}*L332UwgH2PHvf8uxo==IKXH2&sW5G@ za=3#YIuV;qIk7XrH)Ae}O>TQfI$*KG$eZU<2dS_I|I+I$nuAv{IiRh{9Yflg=>QSV z#+J$10&(d>&59iS58CL?Nz0F+&6Aey@@T~%5%wd)N4+sEA+SZGAaP3fmVi-G{A;yc z=am}M{J((?Neorpb&blJw@3`t+*Q#Rf`mZ*liRlf^o8>W>b+uYG{;^PiEYjVOv~>X z^w+;H1=*9kdF+`_j}>g|i#$|4h!RslkAjpBx36Axv$@+%D{Nz5-u=O@YHWw(#y1TL zWlq6I&lJ&)H_}LJgv}o43%U1%OZ!~fPP#`Q!)`O40j_1YQMx(QQc%$q62eFM5v^eZ z+g72W(->Q+?TiBX;_z-i!t)h;Hp5B360xT>Mc-au?X@TnR2@a?^ntF}ppb87IVpX{2$r zN9!QB*;e-;s98ZjE<@K}pVVv^O~zVCl6UohB#&dNSOtlz-jWi34;0h|;$u%tZtMC8 zc{A_eBUjis6Cev3Eq}iru96l>WYihInX>Y#dLe$X8bmz5;~cazO5xPljJQ~;#cn2B z-u%2gm?k-}e3cCO?iB@2soFs*ea<(ET!-8wrZU_diz}t;v$K$Pf$)Qv zFWj(yc6E$jOP?@Ofcfhk&1cL{WFo}QZ7Io!Hi~83*9oGSAgZ4X|9pi$d7Z_);sUSGFkU3|=Q}j) zcdqXT2L}7EIk4a91cTUKyB08R$ChAF%!fyevfKqEl4anJAgAi&m_))3p8aXV&iF_f^XoO5oi229AB5ruL+|EBX``y&@Qnv!kjc^P5y zYpafW`~xE!GpZeir~69NUJA92JfZT)w=!LYv=Xh}Q3MPg}Z z4(8Ujv=g;+w)`nLX;|CR)WyOX;I`pV3=i@99~=n*W5VelocHv~3kTTx-@*y=4QSn7 z)6Np(ivgcZy5G@&{p7fQbLYTLsT;tI{v#9p^8=KZ4^Y?d({e<|%Uh%EMHaFNZr(q> zj7*;nj9oU<6}uE08%v&zWW@3a6+Oo)1Gy6!s^g!1kB~SV%|apv20d1MP>7Q#6=6#L zc!X*(b&czOlD=M1p!^Fw87^VFF@>);*ureLzD*r=d|US2v|HNf$w-|&nrYe!R1pgm zTf0QC_nJ+cIYF8TbV;?AK+HpPuO)_y`qQGZ*c3l2Hl1Nb{aOw!$3l5iGQnt+}Zomk135*=65oQ|-CO#YcV)71c+OJ9gf_i*H~Z%@uofd zZVMh+>28Y0n@1z=FU3HvTUeAN1)6ti7$vLjDO{`2FqOP0P+#Tm?~4xt;eJ@r8X%EO zLa1U5$F!*sR7ia5q$Jg@-F0!RzT{|pLC?g%G)jlCAgKB~b6F7cY9U2c6^N))j*t)~ zA7?{{dKkc)?Zap_KOuY;uSKfDu}BvCTSAHXvZ_6*UeQcLqM?;|P(xdqy24sdODhF@ z?n|ns*nU^|s)^9VW7&#!5>?~uF#mQ_Nx~g#)s7hQvVx5?Nv$&Io*t!D+EA>^(M?sAO3W@^XdCoyp7i#oygH!ta%l95;`f7wjPrIow-;@`&330o zIjP}zYDC=m5}7>E-8A1FQyWSubQ`4PtK6@^u*__~l0aCR279b+6bwCRn2zMe6XF!V z%RfEH(L<|DGH$R4uiFr?UZk0p@_%Q_veIs$)b~oKojH*AGwS_PB;{JZp4)Aj9h?zD>AE(?qAP8l99L6=l(l9KqEDwP^@^W?73Bk58vzd}L%WxY%+~ z^urglc(a-sT7i~ z^{~waLmlUU`Y(Ibe(2l!%)Fm{1)|?5zc-7a8~@g`ORSo-l{M+H{i-xL0K1LKH~#L9 z^$}L@lO1iXJcJOX9nsU87I6fsmAK)P_T~%Ewc!zwOu?NxhK`&gko-+r`IMISmFuEz z&jSK(4T2|g{0E_HEVxt(=5afDNemYDBaKQ#w2^OC-nj4*ER8@PI5au9O zh?x|>?_FsnZ@_l7X1lvSNL);I)-;kyvf@U>wF-+i73b{yTWj5Nwg$R-ehzgP6l*xM zbxk9(jr^ab14uvp{G%>b+L$WAsl?0iZb6?Yye$R75|iREnZW%=DA{eI^q%WLQyIY&M`-Cv{|y> zn-{tEplFpXuU;_)UtQJ-p$nO0T$^EGeZ1GM+})YmEcAE;MMhZYg&r^6M>0_LH+dRQ z@qgVb$$ObLe)|xbmjki8IB38*o?Gl%q(#|H9N|i0#cW6@B!wkeufmWMWfe16Jb7z| z+5XY~*{%M@$fWNk3K15wF2h*1bNc%m<8MB#cIhX6oY6nx>0bF_(Gk3N!?59~Vb<^6 zr;86~V-TU(Q3s$?N|z>k(Xca=G)N`-xwti7Bt2^T3&X=EUm^ftFyZR;(6 zt~aIAhrLwclx0^nzY4-Ht7j@Y7}{MpUVQ0tW?IB^ znzU)rNc#L1tI7#PdauB1BXtd96Y4qI{1Q!9fekImbBqlV$#`eqR+(9MRhiW-9>0ZX zVGA|c=vC&ouI#@|zWwf<*@WbW*6mSH)w$Z$YBHwPA}7D~tx9XCE{a2=iGh$+9>o8+ z1d2a`zPreur?XYw=g_0Mq(`pL$G=8{hhO^uOw4Omi?l7JSR>U?MM1SB-4E4$*}#lOp9?ZF(fbSc%CwYzp{!s)}8=yT@xuc|i$tZ0zC z3`l0K#@h|Pzx;-I-L!*bnIyUNL2Rl^9)vo)&6rm@%{G;3Hh;=I(>C3f+c~K&yqZ&w zO90 zq6pc-3!lihsRe0pbyd;azbCTxO~vBj{hHW&4C{CIgu=00((e*EHl*MYrstQ{P!ky7 zP9$oX4W}#RFs3khBNbAHONcQi+g+|A}e4Ad@6EKm% zie&o_pFO&#Y~&$=WkGQhbXx^anDXgoucnp@7g9t7d1i|*d`pRFWt56xT3?kKteYtx zq59ma$BsOF^H|p7O4ChgHOtRejr(5j?sk9pkUTWBe}&RtvqyH?rFeF? z@>ox$6; zS1X_9;8r|Y>Uh3`HT9Z&-rN}(MVc{zXO?%wC5p1nMTVlXa3cl5Z_j zYaCyBS0A-xc}yeDCEj~=Mg)BYJ*|viYEXZJ21Ht8C+MEHOh#(x_i|pQOMI*E+d3XY zL!lY^V?@YM-hT1)?drL2+A|*g28UBmRS(tGna=M&a9r|11#ZUOy(~i7rB`Hn-#zL3 zeuRAM^H{3nVj1lv{Wg3nsl~hQcx7NeexG`_w&z|Oq?`>yLBv8A0+(V5kO8y%UA`5` zFN1S9tNLIWmP9j*dyAJdzTA8GC_ONaf1j#Ov=99TZxMHc{BovTg=11|gaVk)@-i}# z2Q=^rbd6{}hH~C$#}LYFNIEG?H#0QZ269C925XPee5R^7$AA5~Y7H~dJku``hSMC&QxW?L$8apuPBEj901rQ3PSu?;yc zv`A&cGpf%c8Ws9;ZkczEn$jj-s&+?rk`=~&CzdIq-QQy9CXCC-*J=)O$+%&26ccof zC+jjKK9jGBPloH^EwRtC3|%HW3mn1ihB@>D*9-3R#5qH*B)#6Uc(Fo0OR&W_`IYAk zsVVi_8Iz5;LP(BQ$}Ckt{WG=V?8B~Q;~*5nTVXqyKyx~>P06rAnX5Gq;=^H4IeX78 zBM~#Kv2NWO(DVCD7rLnu(_(XD#mP*{f@v7-X zzr`osxvtJ)C~d$b2vae}nc&)dZW)XO-g;~|J{H8WqryjjQE zqKdt}V*y3Sn>1Z-IM$*Wbng3Zlh>EkPQsyZ`Gj;YR>h5cfdXU3zFy9@QfRYfMi$SY zw>iy3&$$D>+{ef-uO++EM|zLT(?>$uqj~1fX!40@cnX@YoiE+F9mhQ0`E_xsjdB+E z$k&+xHm#d?tND?_SGN@9ZWF=#1Z>}z#P$`;b-y3Yik#gY;M}1>vbe>e<|&*sY*=c` zv0w&ADaCi_oD!p$q;pgG{pxDdQTtKj47dC)jAD1W?+CsuYWBrB_7yE0m-_hB9lLRxBr8CFdRuagpVZSYocc?MY=k&26DMi0=` z3vJV%J>bQ8X&G3SxlJ09PIF9kk2`ZaS?W3AJ#OCF*DvQBUJ#Zd#I*U2>Zp%1Tb51G z%EWV=A%5NdS2HWe9!RaU24z;xeKe=saN_e$I-BKmz!aifF?WUTz=!G9{PqpLqjjq1 z?zq0)=yTVbo?Yy_t6;V~db7ine}A3dExM&_VeU4+cMqBgziED8=8}0ob44XhA9M5S zHU2hqi)WM%#g&enM^P=*lRidXS2Qd zSa+JJ{X1QrQP0e63xtgFAGP8g@;81BPk51bp^P8h@n9fOK8*@3O=IZW)n~Z09Z&oD zB}MmVt>y?XjnBr{HdKvjNe$<=y>kMD`X3FRZEzSWl^PqLGrbWa8bIvk(sHGi-b7^a znU6kl(igX8G;GqB;LhY5qx9>?;4}J28xK2@$!2t&>NCo=DQ|3>2@8{Sz;At#+QC?y zrC3_Ak#80SE1sa>inRS0he2VTz_r!f4hP=Nk zZdm%}qhM^hiAf#j;@BMpM$;Q$>#8V}BZX~14=#1L%gtassVI#xc2X%$2qVth5NsV! z7F=cLO7vM7=ay%~XQj>$9J5DxSwmC2Pd^;%Y}+6wmF2hD-M>=y`Mu9w7rhPnWEuI)J#9KM&+RCpAgVO z*GogQ@qB^~j~8Eylms7kJprjB2-fru<(Aw%!##J+q4+u{vD7)u`wrO*db&*y^1k~W z#D2HFc-*1fJbUJ01M1Gdkj6iEG68HK0s`at#Tx(I`1Ct3c)FkGKkFNr!x3LpKGj_9+WY8s2mI=e;wd;-BV=2CJh2d|naQ8*%Tkb!} zkESPLl$*^k<4d{v;pKHM;c7l>KX=ngm84;W<)%*qx#jKmor%HoJ~=OhudUA{e?tmu zcPC<#9k3uQAC_orJgIY1L-~$q?D>vdrv9efe}#SBbC1j58IFDb8^NOU@9&47e|m;A z8>T|JdZy&Okl4DYw91Buzj{F5fN^H)Ch}>(CoHw>F?DPrqSgV5;T*R5P+Y2vb6@1n zhJSesUy7jmNXo*#bi+Tk>?Y%V@1S!GSvQ3VKhd`AbU4pkET2w0OdRP&ip)7wH=EX` z;s@@NGhlPMPWa;9sz2A!+-5ag8kg6^w-Ymzq8IKgfd2S%JNI7iYrPg z{%^4SJijXXzlr2O-8c(a;Lkns7(V>JBl*Q;B`|Ys=!e2!HzrzC*Q1@^K{0y>o zX7(5yFkq{p%q@XUu7F=e6xg1RI`N2LriikWDar{$?X%080*(wz7mr^_>aGqBHYi(+ zd*j4+0rdN1QURU$%Pj*wQK{NViZ)mu0=NNqArK(I!Msoe7y&T%2qYAs`;mYQbL9c^ zBH&;?ejpC)xaZ{ou9!Fk6NiEk{4gLN4;TT+5hr;7R{>BS0SC$go0|C$JU{^AfK$Q1 z0K@73fbwMb{(lE02E$V~%zuaBPX`B>`zI`1GACm^b@-SX0gf90hZC;{Mu}>tyZ3){ zVVrJ}{jG!lP&MYvz^U6x-qI9P)5(VPU*`Z^F-Hh~8zF$eU&f;1WN+$f0-RxCH!-qw zvIj%2LwT=5!0Z+-E)LED+`w51Kx*z}fYU_mKKDJckq z2MK}jN&-O)0^x%LS4@Bc_YmNUfB=3m2m}tqVL%=@5czcl394-oixegr^-!j`WCVDIoledesatxYFm{Sr ue%0*lT>uX*X3aT?V-|V9^Li2oY}?tz$jRlzvY~J|a2kMxMN(M`^uGYERL - - - - - - - - - - - Регулярные (Тип 3) - Контекстно-свободные (Тип 2) - Контекстно-зависимые (Тип 1) - Неограниченные (Тип 0) - - diff --git a/tex/figures/GLR/CLR_example.tex b/tex/figures/GLR/CLR_example.tex deleted file mode 100644 index 8f06101..0000000 --- a/tex/figures/GLR/CLR_example.tex +++ /dev/null @@ -1,99 +0,0 @@ -\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] - \node[r_state] (s_0) - { - $ - \begin{aligned} - S' &\to \cdot S, \{\$\} \\ - S &\to \cdot a S b S, \{\$\} \\ - S &\to \cdot, \{\$\} - \end{aligned} - $ - }; - \node[r_state] (s_1) [below=2.5cm of s_0] - { - $ - \begin{aligned} - S &\to a \cdot S b S, \{\$\} \\ - S &\to \cdot a S b S, \{b\} \\ - S &\to \cdot, \{b\} - \end{aligned} - $ - }; - \node[r_state] (s_2) [below=2.5cm of s_1] - { - $ - \begin{aligned} - S &\to a \cdot S b S, \{b\} \\ - S &\to \cdot a S b S, \{b\} \\ - S &\to \cdot, \{b\} - \end{aligned} - $ - }; - \node[r_state] (s_3) [right=of s_0] - { - $ S' \to S \cdot, \{\$\} $ - }; - \node[r_state] (s_4) [right=of s_1] - { - $ S \to a S \cdot b S, \{\$\} $ - }; - \node[r_state] (s_5) [right=of s_2] - { - $ S \to a S \cdot b S, \{b\} $ - }; - \node[r_state] (s_6) [right=of s_4] - { - $ - \begin{aligned} - S &\to a S b \cdot S, \{\$\} \\ - S &\to \cdot a S b S, \{\$\} \\ - S &\to \cdot, \{\$\} - \end{aligned} - $ - }; - \node[r_state] (s_7) [right=of s_5] - { - $ - \begin{aligned} - S &\to a S b \cdot S, \{b\} \\ - S &\to \cdot a S b S, \{b\} \\ - S &\to \cdot , \{b\} - \end{aligned} - $ - }; - \node[r_state] (s_8) [right=of s_6] - { - $ S \to a S b S \cdot, \{\$\} $ - }; - \node[r_state] (s_9) [right=of s_7] - { - $ S \to a S b S \cdot, \{b\} $ - }; - - \node[num_state] at (s_0.north west) {0}; - \node[num_state] at (s_1.north west) {1}; - \node[num_state] at (s_2.north west) {2}; - \node[num_state] at (s_3.north west) {3}; - \node[num_state] at (s_4.north west) {4}; - \node[num_state] at (s_5.north west) {5}; - \node[num_state] at (s_6.north west) {6}; - \node[num_state] at (s_7.north west) {7}; - \node[num_state] at (s_8.north west) {8}; - \node[num_state] at (s_9.north west) {9}; - - - \path[->] - (s_0) edge [left] node {$a$} (s_1) - edge [above] node {$S$} (s_3) - (s_1) edge [left] node {$a$} (s_2) - edge [above] node {$S$} (s_4) - (s_2) edge [loop below] node {$a$} () - edge [above] node {$S$} (s_5) - (s_4) edge [above] node {$b$} (s_6) - (s_5) edge [above] node {$b$} (s_7) - (s_6) edge [above] node {$S$} (s_8) - edge [above, bend right=20] node {$a$} (s_1) - (s_7) edge [above] node {$S$} (s_9) - edge [below, bend left=20] node {$a$} (s_2) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/GLR_example.tex b/tex/figures/GLR/GLR_example.tex deleted file mode 100644 index 64e9d1a..0000000 --- a/tex/figures/GLR/GLR_example.tex +++ /dev/null @@ -1,101 +0,0 @@ -\begin{tikzpicture}[> = stealth,node distance=1.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] - \node[r_state] (s_0) - { - $ - \begin{aligned} - S' &\to \cdot S \$ \\ - S &\to \cdot a b C \\ - S &\to \cdot a B C - \end{aligned} - $ - }; - \node[r_state] (s_1) [below=2.5cm of s_0] - { - $ S' \to S \cdot \$ $ - }; - \node[r_state] (s_acc) [below=2cm of s_1] - { - $ S' \to S \$ \cdot $ - }; - \node[r_state] (s_2) [right=3cm of s_0] - { - $ - \begin{aligned} - S &\to a \cdot B C \\ - S &\to a \cdot b C \\ - B &\to \cdot b - \end{aligned} - $ - }; - - \node[r_state] (s_3) [right=3cm of s_2] - { - $ - \begin{aligned} - S &\to a b \cdot C \\ - B &\to b \cdot \\ - C &\to \cdot c - \end{aligned} - $ - }; - - \node[r_state] (s_5) [right=3cm of s_3] - { - $ - \begin{aligned} - S &\to a b C \cdot - \end{aligned} - $ - }; - - \node[r_state] (s_4) [below=2.5cm of s_2] - { - $ - \begin{aligned} - S &\to a B \cdot C \\ - C &\to \cdot c - \end{aligned} - $ - }; - - \node[r_state] (s_6) [right=3cm of s_4] - { - $ - \begin{aligned} - C &\to c \cdot - \end{aligned} - $ - }; - - \node[r_state] (s_7) [below=2cm of s_4] - { - $ - \begin{aligned} - S &\to a B C \cdot - \end{aligned} - $ - }; - - \node[num_state] at (s_0.north west) {0}; - \node[num_state] at (s_1.north west) {1}; - \node[num_state] at (s_2.north west) {2}; - \node[num_state] at (s_3.north west) {3}; - \node[num_state] at (s_4.north west) {4}; - \node[num_state] at (s_5.north west) {5}; - \node[num_state] at (s_6.north west) {6}; - \node[num_state] at (s_7.north west) {7}; - \node[num_state] at (s_acc.north west) {acc}; - - - \path[->] - (s_0) edge [above] node {$a$} (s_2) - edge [right] node {$S$} (s_1) - (s_1) edge [right] node {$\$$} (s_acc) - (s_2) edge [above] node {$b$} (s_3) - edge [right] node {$B$} (s_4) - (s_3) edge [above] node {$C$} (s_5) - edge [right] node {$c$} (s_6) - (s_4) edge [above] node {$c$} (s_6) - edge [right] node {$C$} (s_7) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LL_LR.tex b/tex/figures/GLR/LL_LR.tex deleted file mode 100644 index 3d3eaeb..0000000 --- a/tex/figures/GLR/LL_LR.tex +++ /dev/null @@ -1,21 +0,0 @@ -\begin{tikzpicture} - \node at (0,0) (ll0) {LL(0)}; - \node at (0,3.5) (ll1) {LL(1)}; - \node at (0,4.5) (llk) {LL(k)}; - \node at (3,0) (lr0) {LR(0)}; - \node at (3,1.5) (slr) {SLR(1)}; - \node at (3,2.5) (lalr) {LALR(1)}; - \node at (3,3.5) (clr) {CLR(1)}; - \node at (3,4.5) (lrk) {LR(k)}; - - \node[r_state,violet,fit=(ll0)] (a) {}; - \node[draw=none,fit=(a)] (a1) {}; - \node[draw=none,fit=(a1)] (a2) {}; - \node[r_state,violet,fit=(ll0) (ll1) (a)] (b) {}; - \node[r_state,violet,fit=(ll0) (llk) (b)] (c) {}; - \node[r_state,fit=(a2) (lr0)] (d) {}; - \node[r_state,fit=(slr) (d)] (e) {}; - \node[r_state,fit=(lalr) (e)] (f) {}; - \node[r_state,fit=(lalr) (clr) (f) (b)] (g) {}; - \node[r_state,fit=(g) (lalr) (lrk) (c)] (h) {}; -\end{tikzpicture} diff --git a/tex/figures/GLR/LR0/complete.tex b/tex/figures/GLR/LR0/complete.tex deleted file mode 100644 index ef2143e..0000000 --- a/tex/figures/GLR/LR0/complete.tex +++ /dev/null @@ -1,67 +0,0 @@ -\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] - \node[r_state] (s_0) - { - $ - \begin{aligned} - S' &\to \cdot S \$ \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - \node[r_state] (s_1) [right=of s_0] - { - $ S' \to S \cdot \$ $ - }; - \node[r_state] (s_2) [right=of s_1] - { - $ S' \to S \$ \cdot $ - }; - \node[r_state] (s_3) [below=2.5cm of s_0] - { - $ - \begin{aligned} - S &\to a \cdot S b S \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - \node[r_state] (s_4) [right=of s_3] - { - $ S \to a S \cdot b S$ - }; - \node[r_state] (s_5) [right=of s_4] - { - $ - \begin{aligned} - S &\to a S b \cdot S \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - \node[r_state] (s_6) [right=of s_5] - { - $ S \to a S b S \cdot$ - }; - - \node[num_state] at (s_0.north west) {0}; - \node[num_state] at (s_1.north west) {1}; - \node[num_state] at (s_2.north west) {2}; - \node[num_state] at (s_3.north west) {3}; - \node[num_state] at (s_4.north west) {4}; - \node[num_state] at (s_5.north west) {5}; - \node[num_state] at (s_6.north west) {6}; - - \path[->] - (s_0) edge [left] node {$a$} (s_3) - edge [above] node {$S$} (s_1) - (s_1) edge [above] node {$\$$} (s_2) - (s_3) edge [above] node {$S$} (s_4) - edge [loop below] node {$a$} () - (s_4) edge [above] node {$b$} (s_5) - (s_5) edge [above] node {$S$} (s_6) - edge [above, bend right=20] node {$a$} (s_3) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state0.tex b/tex/figures/GLR/LR0/state0.tex deleted file mode 100644 index b0b662f..0000000 --- a/tex/figures/GLR/LR0/state0.tex +++ /dev/null @@ -1,14 +0,0 @@ -\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] - \node[r_state] (s_0) - { - $ - \begin{aligned} - S' &\to \cdot S \$ \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - - \node[num_state] at (s_0.north west) {0}; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state1.tex b/tex/figures/GLR/LR0/state1.tex deleted file mode 100644 index 06edbd2..0000000 --- a/tex/figures/GLR/LR0/state1.tex +++ /dev/null @@ -1,23 +0,0 @@ -\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] - \node[r_state] (s_0) - { - $ - \begin{aligned} - S' &\to \cdot S \$ \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - \node[r_state] (s_1) [right=of s_0] - { - $ S' \to S \cdot \$ $ - }; - - \node[num_state] at (s_0.north west) {0}; - \node[num_state] at (s_1.north west) {1}; - - \path[->] - (s_0) edge [above] node {$S$} (s_1) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state2.tex b/tex/figures/GLR/LR0/state2.tex deleted file mode 100644 index aefec37..0000000 --- a/tex/figures/GLR/LR0/state2.tex +++ /dev/null @@ -1,29 +0,0 @@ -\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] - \node[r_state] (s_0) - { - $ - \begin{aligned} - S' &\to \cdot S \$ \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - \node[r_state] (s_1) [right=of s_0] - { - $ S' \to S \cdot \$ $ - }; - \node[r_state] (s_2) [right=of s_1] - { - $ S' \to S \$ \cdot $ - }; - - \node[num_state] at (s_0.north west) {0}; - \node[num_state] at (s_1.north west) {1}; - \node[num_state] at (s_2.north west) {2}; - - \path[->] - (s_0) edge [above] node {$S$} (s_1) - (s_1) edge [above] node {$\$$} (s_2) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state3.tex b/tex/figures/GLR/LR0/state3.tex deleted file mode 100644 index 74b9fe1..0000000 --- a/tex/figures/GLR/LR0/state3.tex +++ /dev/null @@ -1,42 +0,0 @@ -\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] - \node[r_state] (s_0) - { - $ - \begin{aligned} - S' &\to \cdot S \$ \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - \node[r_state] (s_1) [right=of s_0] - { - $ S' \to S \cdot \$ $ - }; - \node[r_state] (s_2) [right=of s_1] - { - $ S' \to S \$ \cdot $ - }; - \node[r_state] (s_3) [below=2.5cm of s_0] - { - $ - \begin{aligned} - S &\to a \cdot S b S \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - - \node[num_state] at (s_0.north west) {0}; - \node[num_state] at (s_1.north west) {1}; - \node[num_state] at (s_2.north west) {2}; - \node[num_state] at (s_3.north west) {3}; - - \path[->] - (s_0) edge [left] node {$a$} (s_3) - edge [above] node {$S$} (s_1) - (s_1) edge [above] node {$\$$} (s_2) - (s_3) edge [loop below] node {$a$} () - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state4.tex b/tex/figures/GLR/LR0/state4.tex deleted file mode 100644 index 79227e8..0000000 --- a/tex/figures/GLR/LR0/state4.tex +++ /dev/null @@ -1,48 +0,0 @@ -\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] - \node[r_state] (s_0) - { - $ - \begin{aligned} - S' &\to \cdot S \$ \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - \node[r_state] (s_1) [right=of s_0] - { - $ S' \to S \cdot \$ $ - }; - \node[r_state] (s_2) [right=of s_1] - { - $ S' \to S \$ \cdot $ - }; - \node[r_state] (s_3) [below=2.5cm of s_0] - { - $ - \begin{aligned} - S &\to a \cdot S b S \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - \node[r_state] (s_4) [right=of s_3] - { - $ S \to a S \cdot b S$ - }; - - \node[num_state] at (s_0.north west) {0}; - \node[num_state] at (s_1.north west) {1}; - \node[num_state] at (s_2.north west) {2}; - \node[num_state] at (s_3.north west) {3}; - \node[num_state] at (s_4.north west) {4}; - - \path[->] - (s_0) edge [left] node {$a$} (s_3) - edge [above] node {$S$} (s_1) - (s_1) edge [above] node {$\$$} (s_2) - (s_3) edge [above] node {$S$} (s_4) - edge [loop below] node {$a$} () - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state5.tex b/tex/figures/GLR/LR0/state5.tex deleted file mode 100644 index 6545b4e..0000000 --- a/tex/figures/GLR/LR0/state5.tex +++ /dev/null @@ -1,62 +0,0 @@ -\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] - - \node[r_state] (s_0) - { - $ - \begin{aligned} - S' &\to \cdot S \$ \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - \node[r_state] (s_1) [right=of s_0] - { - $ S' \to S \cdot \$ $ - }; - \node[r_state] (s_2) [right=of s_1] - { - $ S' \to S \$ \cdot $ - }; - \node[r_state] (s_3) [below=2.5cm of s_0] - { - $ - \begin{aligned} - S &\to a \cdot S b S \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - \node[r_state] (s_4) [right=of s_3] - { - $ S \to a S \cdot b S$ - }; - \node[r_state] (s_5) [right=of s_4] - { - $ - \begin{aligned} - S &\to a S b \cdot S \\ - S &\to \cdot a S b S \\ - S &\to \cdot - \end{aligned} - $ - }; - - \node[num_state] at (s_0.north west) {0}; - \node[num_state] at (s_1.north west) {1}; - \node[num_state] at (s_2.north west) {2}; - \node[num_state] at (s_3.north west) {3}; - \node[num_state] at (s_4.north west) {4}; - \node[num_state] at (s_5.north west) {5}; - - \path[->] - (s_0) edge [left] node {$a$} (s_3) - edge [above] node {$S$} (s_1) - (s_1) edge [above] node {$\$$} (s_2) - (s_3) edge [above] node {$S$} (s_4) - edge [loop below] node {$a$} () - (s_4) edge [above] node {$b$} (s_5) - (s_5) edge [above, bend right=20] node {$a$} (s_3) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/cfl/pumping0.tex b/tex/figures/cfl/pumping0.tex deleted file mode 100644 index 5c1e05a..0000000 --- a/tex/figures/cfl/pumping0.tex +++ /dev/null @@ -1,26 +0,0 @@ - -\begin{tikzpicture} - \node[draw=none, fill=none] at (0, 4) {S}; - \node[draw=none, fill=none] at (0.1, 1) {A}; - - \draw (-1,0) -- (0,3.8); - \draw (0,3.8) -- (1,0); - - \draw (-0.5,0) -- (0.1,0.8); - \draw (0.1,0.8) -- (0.5,0); - - \fill[Orchid] (-1,-0.5) rectangle ++(0.5,0.5); - \fill[LimeGreen] (-0.5,-0.5) rectangle ++(1,0.5); - \fill[Turquoise] (0.5,-0.5) rectangle ++(0.5,0.5); - - \draw[draw=black] (-1,-0.5) rectangle ++(2,0.5); - \draw[draw=black] (-0.5,-0.5) rectangle ++(1,0.5); - - \draw [thick,densely dotted, rounded corners=1mm] (0,3.8) -- (-0.1, 2.5) -- (0.15, 1.4) -- (0.1, 1.1); - - - \node[draw=none, fill=none] at (-0.75,-0.25) {$u$}; - \node[draw=none, fill=none] at (0,-0.25) {$w$}; - \node[draw=none, fill=none] at (0.75,-0.25) {$y$}; -\end{tikzpicture} - diff --git a/tex/figures/cfl/pumping1.tex b/tex/figures/cfl/pumping1.tex deleted file mode 100644 index 02cd0b6..0000000 --- a/tex/figures/cfl/pumping1.tex +++ /dev/null @@ -1,34 +0,0 @@ - -\begin{tikzpicture} - \node[draw=none, fill=none] at (0, 4) {S}; - \node[draw=none, fill=none] at (-0.1, 2.3) {A}; - \node[draw=none, fill=none] at (0.1, 1) {A}; - - \draw (-1.5,0) -- (0,3.8); - \draw (0,3.8) -- (1.5,0); - \draw (-1,0) -- (-0.1,2.1); - \draw (-0.1,2.1) -- (1,0); - \draw (-0.5,0) -- (0.1,0.8); - \draw (0.1,0.8) -- (0.5,0); - - \fill[Orchid] (-1.5,-0.5) rectangle ++(0.5,0.5); - \fill[Dandelion] (-1,-0.5) rectangle ++(0.5,0.5); - \fill[LimeGreen] (-0.5,-0.5) rectangle ++(1,0.5); - \fill[Salmon] (0.5,-0.5) rectangle ++(0.5,0.5); - \fill[Turquoise] (1,-0.5) rectangle ++(0.5,0.5); - - \draw[draw=black] (-1.5,-0.5) rectangle ++(3,0.5); - \draw[draw=black] (-1,-0.5) rectangle ++(2,0.5); - \draw[draw=black] (-0.5,-0.5) rectangle ++(1,0.5); - - \draw [thick,densely dotted, rounded corners=1mm](0,3.8) -- (0.1, 2.9) -- (-0.15, 2.7) -- (-0.1, 2.4); - - \draw [thick,densely dotted, rounded corners=1mm](-0.1, 2.1) -- (-0.1, 1.7) -- (0.15, 1.4) -- (0.1, 1.1); - - - \node[draw=none, fill=none] at (-1.25,-0.25) {$u$}; - \node[draw=none, fill=none] at (-0.75,-0.25) {$v$}; - \node[draw=none, fill=none] at (0,-0.25) {$w$}; - \node[draw=none, fill=none] at (0.75,-0.25) {$x$}; - \node[draw=none, fill=none] at (1.25,-0.25) {$y$}; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/cfl/pumping2.tex b/tex/figures/cfl/pumping2.tex deleted file mode 100644 index e645f44..0000000 --- a/tex/figures/cfl/pumping2.tex +++ /dev/null @@ -1,40 +0,0 @@ -\begin{tikzpicture} - \node[draw=none, fill=none] at (0, 4) {S}; - \node[draw=none, fill=none] at (-0.1, 2.8) {A}; - \node[draw=none, fill=none] at (0.1, 1.6) {A}; - \node[draw=none, fill=none] at (-0, 0.8) {A}; - - \draw (-2,0) -- (0,3.8); - \draw (0,3.8) -- (2,0); - \draw (-1.5,0) -- (-0.1,2.6); - \draw (-0.1,2.6) -- (1.5,0); - \draw (-1,0) -- (0.1,1.4); - \draw (0.1,1.4) -- (1,0); - \draw (-0.5,0) -- (0,0.6); - \draw (0,0.6) -- (0.5,0); - - \fill[Orchid] (-2,-0.5) rectangle ++(0.5,0.5); - \fill[Dandelion] (-1.5,-0.5) rectangle ++(1,0.5); - \fill[LimeGreen] (-0.5,-0.5) rectangle ++(1,0.5); - \fill[Salmon] (0.5,-0.5) rectangle ++(1,0.5); - \fill[Turquoise] (1.5,-0.5) rectangle ++(0.5,0.5); - - \draw[draw=black] (-2,-0.5) rectangle ++(4,0.5); - \draw[draw=black] (-1.5,-0.5) rectangle ++(3,0.5); - \draw[draw=black] (-1,-0.5) rectangle ++(2,0.5); - \draw[draw=black] (-0.5,-0.5) rectangle ++(1,0.5); - - \draw [thick,densely dotted, rounded corners=1mm](0,3.8) -- (0.1, 3.4) -- (-0.15, 3.2) -- (-0.1, 2.9); - - \draw [thick,densely dotted, rounded corners=1mm](-0.1, 2.6) -- (-0.1, 2.3) -- (0.15, 1.9) -- (0.1, 1.75); - - \draw [thick,densely dotted, rounded corners=1mm](0.1,1.4) -- (-0.05, 1.1) -- (0, 1); - - \node[draw=none, fill=none] at (-1.75,-0.25) {$u$}; - \node[draw=none, fill=none] at (-1.25,-0.25) {$v$}; - \node[draw=none, fill=none] at (-0.75,-0.25) {$v$}; - \node[draw=none, fill=none] at (0,-0.25) {$w$}; - \node[draw=none, fill=none] at (0.75,-0.25) {$x$}; - \node[draw=none, fill=none] at (1.25,-0.25) {$x$}; - \node[draw=none, fill=none] at (1.75,-0.25) {$y$}; - \end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/cfl/tree0.tex b/tex/figures/cfl/tree0.tex deleted file mode 100644 index e32f10e..0000000 --- a/tex/figures/cfl/tree0.tex +++ /dev/null @@ -1,27 +0,0 @@ -\begin{tikzpicture}[sibling distance=4em, - every node/.style = {shape=rectangle, rounded corners, - draw, align=center}]] - \node {S} - child { node {a} } - child { node {S} - child { node {$\varepsilon$}} - } - child { node {b} } - child { node {S} - child {node {a}} - child { node {S} - child { node {$\varepsilon$}} - } - child { node {b} } - child { node {S} - child {node {a}} - child {node {S} - child {node {$\varepsilon$}} - } - child {node {b}} - child {node {S} - child {node {$\varepsilon$}} - } - } - }; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/cyk/graph1.tex b/tex/figures/cyk/graph1.tex deleted file mode 100644 index 407d0ca..0000000 --- a/tex/figures/cyk/graph1.tex +++ /dev/null @@ -1,19 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge[left] node {$\{A\}$} (q_1) - (q_1) edge[above] node[yshift=5pt] {$\{A\}$} (q_2) - (q_2) edge[below] node[yshift=-5pt] {$\{A\}$} (q_0) - (q_2) edge[bend left, above] node {$\{B\}$} (q_3) - (q_3) edge[bend left, below] node {$\{B\}$} (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/flpq/path1.tex b/tex/figures/flpq/path1.tex deleted file mode 100644 index 14d88f8..0000000 --- a/tex/figures/flpq/path1.tex +++ /dev/null @@ -1,8 +0,0 @@ -\begin{tikzpicture}[node distance=2cm, shorten >=1pt,on grid,auto] - \node[state] (q_1) {$1$}; - \node[state] (q_2) [right=of q_1] {$2$}; - \node[state] (q_3) [right=of q_2] {$3$}; - \path[->] - (q_1) edge node {a} (q_2) - (q_2) edge node {b} (q_3); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/flpq/path2.tex b/tex/figures/flpq/path2.tex deleted file mode 100644 index 62a7a83..0000000 --- a/tex/figures/flpq/path2.tex +++ /dev/null @@ -1,12 +0,0 @@ -\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] - \node[state] (q_0) {$0$}; - \node[state] (q_1) [right=of q_0] {$1$}; - \node[state] (q_2) [right=of q_1] {$2$}; - \node[state] (q_3) [right=of q_2] {$3$}; - \node[state] (q_4) [right=of q_3] {$2$}; - \path[->] - (q_0) edge node {a} (q_1) - (q_1) edge node {a} (q_2) - (q_2) edge node {b} (q_3) - (q_3) edge node {b} (q_4); - \end{tikzpicture} diff --git a/tex/figures/gll/complete.tex b/tex/figures/gll/complete.tex deleted file mode 100644 index d2332a6..0000000 --- a/tex/figures/gll/complete.tex +++ /dev/null @@ -1,26 +0,0 @@ -\begin{tikzpicture}[] - \node[state] (q_0) {S, 0}; - \node[state] (q_1) [right=of q_0] {S, 1}; - \node[state] (q_2) [left=of q_0] {S, 2}; - - - \path[->] - (q_0) edge[loop above] node {$S \to S \cdot S S$} - node[below] {1} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {2} () - (q_1) edge[loop above] node {$S \to S \cdot S S$} - node[below] {5} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {6} () - edge[bend left] node[below] {$S \to S S \cdot$} - node[above] {4} (q_0) - edge[bend right] node[above] {$S \to S S \cdot S$} - node[below] {3} (q_0) - (q_2) edge[loop above] node {$S \to S \cdot S S$} - node[below] {8} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {9} () - edge[] node[above] {$S \to S S S \cdot$} node[below] {7} (q_0) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state0.tex b/tex/figures/gll/state0.tex deleted file mode 100644 index 426d077..0000000 --- a/tex/figures/gll/state0.tex +++ /dev/null @@ -1,3 +0,0 @@ -\begin{tikzpicture}[] - \node[state] (q_0) {S, 0}; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state1.tex b/tex/figures/gll/state1.tex deleted file mode 100644 index 4481647..0000000 --- a/tex/figures/gll/state1.tex +++ /dev/null @@ -1,8 +0,0 @@ -\begin{tikzpicture}[] - \node[state] (q_0) {S, 0}; - - \path[->] - (q_0) edge[loop above] node {$S \to S \cdot S S$} - node[below] {1} () - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state2.tex b/tex/figures/gll/state2.tex deleted file mode 100644 index 28b9e57..0000000 --- a/tex/figures/gll/state2.tex +++ /dev/null @@ -1,10 +0,0 @@ -\begin{tikzpicture}[] - \node[state] (q_0) {S, 0}; - - \path[->] - (q_0) edge[loop above] node {$S \to S \cdot S S$} - node[below] {1} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {2} () - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state3.tex b/tex/figures/gll/state3.tex deleted file mode 100644 index 22fac6a..0000000 --- a/tex/figures/gll/state3.tex +++ /dev/null @@ -1,13 +0,0 @@ -\begin{tikzpicture}[] - \node[state] (q_0) {S, 0}; - \node[state] (q_1) [right=of q_0] {S, 1}; - - \path[->] - (q_0) edge[loop above] node {$S \to S \cdot S S$} - node[below] {1} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {2} () - (q_1) edge[bend right] node[above] {$S \to S S \cdot S$} - node[below] {3} (q_0) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state4.tex b/tex/figures/gll/state4.tex deleted file mode 100644 index 58ba3a4..0000000 --- a/tex/figures/gll/state4.tex +++ /dev/null @@ -1,15 +0,0 @@ -\begin{tikzpicture}[] - \node[state] (q_0) {S, 0}; - \node[state] (q_1) [right=of q_0] {S, 1}; - - \path[->] - (q_0) edge[loop above] node {$S \to S \cdot S S$} - node[below] {1} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {2} () - (q_1) edge[bend left] node[below] {$S \to S S \cdot$} - node[above] {4} (q_0) - edge[bend right] node[above] {$S \to S S \cdot S$} - node[below] {3} (q_0) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state5.tex b/tex/figures/gll/state5.tex deleted file mode 100644 index e8e80aa..0000000 --- a/tex/figures/gll/state5.tex +++ /dev/null @@ -1,17 +0,0 @@ -\begin{tikzpicture}[] - \node[state] (q_0) {S, 0}; - \node[state] (q_1) [right=of q_0] {S, 1}; - - \path[->] - (q_0) edge[loop above] node {$S \to S \cdot S S$} - node[below] {1} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {2} () - (q_1) edge[loop above] node {$S \to S \cdot S S$} - node[below] {5} () - edge[bend left] node[below] {$S \to S S \cdot$} - node[above] {4} (q_0) - edge[bend right] node[above] {$S \to S S \cdot S$} - node[below] {3} (q_0) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state6.tex b/tex/figures/gll/state6.tex deleted file mode 100644 index 69d88b8..0000000 --- a/tex/figures/gll/state6.tex +++ /dev/null @@ -1,19 +0,0 @@ -\begin{tikzpicture}[] - \node[state] (q_0) {S, 0}; - \node[state] (q_1) [right=of q_0] {S, 1}; - - \path[->] - (q_0) edge[loop above] node {$S \to S \cdot S S$} - node[below] {1} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {2} () - (q_1) edge[loop above] node {$S \to S \cdot S S$} - node[below] {5} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {6} () - edge[bend left] node[below] {$S \to S S \cdot$} - node[above] {4} (q_0) - edge[bend right] node[above] {$S \to S S \cdot S$} - node[below] {3} (q_0) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state7.tex b/tex/figures/gll/state7.tex deleted file mode 100644 index 1e57543..0000000 --- a/tex/figures/gll/state7.tex +++ /dev/null @@ -1,22 +0,0 @@ -\begin{tikzpicture}[] - \node[state] (q_0) {S, 0}; - \node[state] (q_1) [right=of q_0] {S, 1}; - \node[state] (q_2) [left=of q_0] {S, 2}; - - - \path[->] - (q_0) edge[loop above] node {$S \to S \cdot S S$} - node[below] {1} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {2} () - (q_1) edge[loop above] node {$S \to S \cdot S S$} - node[below] {5} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {6} () - edge[bend left] node[below] {$S \to S S \cdot$} - node[above] {4} (q_0) - edge[bend right] node[above] {$S \to S S \cdot S$} - node[below] {3} (q_0) - (q_2) edge[] node[above] {$S \to S S S \cdot$} node[below] {7} (q_0) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state8.tex b/tex/figures/gll/state8.tex deleted file mode 100644 index f377e2c..0000000 --- a/tex/figures/gll/state8.tex +++ /dev/null @@ -1,24 +0,0 @@ -\begin{tikzpicture}[] - \node[state] (q_0) {S, 0}; - \node[state] (q_1) [right=of q_0] {S, 1}; - \node[state] (q_2) [left=of q_0] {S, 2}; - - - \path[->] - (q_0) edge[loop above] node {$S \to S \cdot S S$} - node[below] {1} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {2} () - (q_1) edge[loop above] node {$S \to S \cdot S S$} - node[below] {5} () - edge[loop below] node {$S \to S \cdot S$} - node[above] {6} () - edge[bend left] node[below] {$S \to S S \cdot$} - node[above] {4} (q_0) - edge[bend right] node[above] {$S \to S S \cdot S$} - node[below] {3} (q_0) - (q_2) edge[loop above] node {$S \to S \cdot S S$} - node[below] {8} () - edge[] node[above] {$S \to S S S \cdot$} node[below] {7} (q_0) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph0.tex b/tex/figures/graph/graph0.tex deleted file mode 100644 index 421e512..0000000 --- a/tex/figures/graph/graph0.tex +++ /dev/null @@ -1,19 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge[left] node {a} (q_1) - (q_1) edge[above] node {a} (q_2) - (q_2) edge[below] node {a} (q_0) - (q_2) edge[bend left, above] node {b} (q_3) - (q_3) edge[bend left, below] node {b} (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph1.tex b/tex/figures/graph/graph1.tex deleted file mode 100644 index 322700d..0000000 --- a/tex/figures/graph/graph1.tex +++ /dev/null @@ -1,18 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[] - (q_0) edge (q_1) - (q_1) edge (q_2) - (q_2) edge (q_0) - (q_2) edge (q_3); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph2.tex b/tex/figures/graph/graph2.tex deleted file mode 100644 index 1605ccb..0000000 --- a/tex/figures/graph/graph2.tex +++ /dev/null @@ -1,19 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge (q_1) - (q_1) edge (q_2) - (q_2) edge (q_0) - (q_2) edge [bend left] (q_3) - (q_3) edge [bend left] (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph3.tex b/tex/figures/graph/graph3.tex deleted file mode 100644 index 780b751..0000000 --- a/tex/figures/graph/graph3.tex +++ /dev/null @@ -1,20 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge[left] node {$\{a\}$} (q_1) - (q_1) edge[above] node {$\{a\}$} (q_2) - (q_2) edge[below] node {$\{a\}$} (q_0) - (q_2) edge[bend left = 15, above] node {$\{a\}$} (q_3) - (q_2) edge[bend left = 65, above] node {$\{b\}$} (q_3) - (q_3) edge[bend left, below] node {$\{b\}$} (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph4.tex b/tex/figures/graph/graph4.tex deleted file mode 100644 index 5462c98..0000000 --- a/tex/figures/graph/graph4.tex +++ /dev/null @@ -1,19 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge[left] node {$-1.4$} (q_1) - (q_1) edge[above] node[yshift=5pt] {$2.2$} (q_2) - (q_2) edge[below] node[yshift=-5pt] {$0.5$} (q_0) - (q_2) edge[bend left, above] node {$1.85$} (q_3) - (q_3) edge[bend left, below] node {$-0.76$} (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph5.tex b/tex/figures/graph/graph5.tex deleted file mode 100644 index 75fa0fd..0000000 --- a/tex/figures/graph/graph5.tex +++ /dev/null @@ -1,31 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge[loop below] node {} () - edge node {} (q_1) - edge[bend right] node {} (q_2) - edge[bend right = 55] node {} (q_3) - (q_1) edge[loop above] node {} () - edge[bend right] node {} (q_0) - edge node {} (q_2) - edge[bend left = 55, above] node {} (q_3) - (q_2) edge[loop below] node {} () - edge[bend right] node {} (q_1) - edge node {} (q_0) - edge[bend left, above] node {} (q_3) - (q_3) edge[loop above] node {} () - edge[bend left, below] node {} (q_2) - edge[bend left, below] node {} (q_0) - edge[bend right, below] node {} (q_1) - ; -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph_BFS_1.tex b/tex/figures/graph/graph_BFS_1.tex deleted file mode 100644 index 2e142de..0000000 --- a/tex/figures/graph/graph_BFS_1.tex +++ /dev/null @@ -1,19 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state,fill=yellow] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state,fill=green] (q_2) at (T60.apex) {$2$}; - \node[state,fill=yellow] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge (q_1) - (q_1) edge (q_2) - (q_2) edge (q_0) - (q_2) edge [bend left] (q_3) - (q_3) edge [bend left] (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph_BFS_2.tex b/tex/figures/graph/graph_BFS_2.tex deleted file mode 100644 index 62fe9f2..0000000 --- a/tex/figures/graph/graph_BFS_2.tex +++ /dev/null @@ -1,19 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state,fill=green] (q_0) at (T60.right corner) {$0$}; - \node[state,fill=yellow] (q_1) at (T60.left corner) {$1$}; - \node[state,fill=yellow, draw=red, line width=0.45mm] (q_2) at (T60.apex) {$2$}; - \node[state,fill=green] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge (q_1) - (q_1) edge (q_2) - (q_2) edge (q_0) - (q_2) edge [bend left] (q_3) - (q_3) edge [bend left] (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph_BFS_3.tex b/tex/figures/graph/graph_BFS_3.tex deleted file mode 100644 index 3c581b8..0000000 --- a/tex/figures/graph/graph_BFS_3.tex +++ /dev/null @@ -1,19 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state,fill=green] (q_1) at (T60.left corner) {$1$}; - \node[state,fill=yellow, draw=red, line width=0.45mm] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge (q_1) - (q_1) edge (q_2) - (q_2) edge (q_0) - (q_2) edge [bend left] (q_3) - (q_3) edge [bend left] (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph_MS-BFS_1.tex b/tex/figures/graph/graph_MS-BFS_1.tex deleted file mode 100644 index 01ffb89..0000000 --- a/tex/figures/graph/graph_MS-BFS_1.tex +++ /dev/null @@ -1,19 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state,fill=green] (q_1) at (T60.left corner) {$1$}; - \node[state,fill=yellow] (q_2) at (T60.apex) {$2$}; - \node[state,fill=green] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge (q_1) - (q_1) edge (q_2) - (q_2) edge (q_0) - (q_2) edge [bend left] (q_3) - (q_3) edge [bend left] (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph_MS-BFS_2.tex b/tex/figures/graph/graph_MS-BFS_2.tex deleted file mode 100644 index 6360763..0000000 --- a/tex/figures/graph/graph_MS-BFS_2.tex +++ /dev/null @@ -1,19 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state,fill=yellow] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state,fill=green] (q_2) at (T60.apex) {$2$}; - \node[state,fill=yellow, draw=red, line width=0.45mm] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge (q_1) - (q_1) edge (q_2) - (q_2) edge (q_0) - (q_2) edge [bend left] (q_3) - (q_3) edge [bend left] (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/path0.tex b/tex/figures/graph/path0.tex deleted file mode 100644 index 0d7b638..0000000 --- a/tex/figures/graph/path0.tex +++ /dev/null @@ -1,6 +0,0 @@ -\begin{tikzpicture}[on grid, auto] - \node[state] (v_0) {$v_0$}; - \node[state] (v_n) [right=2.0cm of v_0] {$v_n$}; - \path[->] - (v_0) edge [out=45] node {$\pi$} (v_n); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/mcfg/mcfg.pdf b/tex/figures/mcfg/mcfg.pdf deleted file mode 100644 index dd7aa00c514b7f57bfbf3bc1592652927bb45285..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6679 zcma)>2RvK-zsHRZMHN+aAU0JbA~C8~?7h`)5Tr&(Vm(^BwQ6r3RI6IERw=c`ELBxS zYt>e(c2L|z>$!dYz4vwR$vF9be&@Ho3B|(r7gp&K!a`8T;C;$jRS>L6U zk^%^8AYAOR4gd&2(xU_b0K!U0CoBR@I6J|y2nB=<$`(N>Elr8Rq7iUsO0U124K=l| zf@tgZjqxcjJ~vH8m)>{Mm6LaUJbKmj#iPgh3FOP!ehoIOkN8!CJ7()LqIYV`FIGey zF-~8IX4S(54^#$ugIz}UJe-An#rOBx0S0X4(c8k~HD8acX1{hyx^53YF8AE-nN%5; zu0C_-Y^Qw$KPxc%I4dfIruX3+VVr{pI^J>j3;o1p z);<=YzI@*)I4HYfdF#uk8_?)Jb(n`ANp;Ee)*T^B#;VOAQ>*TlmGy5PM-^i!52~JV zKB-50HQ{suEwUu;jLwzq*S43vVGW=t-W%b4z$@)@-7LjwMd;7;V=ucPo zw64f~wV_27sJLOd(4oE&lJ_31H!kbVpU=b7Kl?Pb^8Fm!&RdIU1177%o$-h9VHBxn zqthiO!|!>7^KWlWds7H(=grSqwNY9A2<}O0Ty-&O{@$z3{n3fkY=I}nlddK|jJ_;! zRJOm^RFg|}Qn~3qNtEDbyC3S1^wX4sEG5Fl_E#Dceh~|RnDxXnA@9Y2Kw>-50{>GU z#|5G2g;mza5{dyJB}EhnhcFySFaW|ZIRFSCYy&5J6H0{8@bg<(3FU(Q?P@zgpdb(c zJt;B5MTGaS$wdB{3?OXa?TP>h>%i?10B!*2cyb*$8bKHfbkbK?6Jd*l%cHyiW&{Zc z0E>ZyprSws7z_{ri3mYNK@gAxz~Z~!M8I5vx{cUAGXFOI7GM$^Us?T2mk?#1OIgsnlbkAGEhvCan~NGJ5cc)U%~PQW8-MDgF*vh zXyt*{SLIlBnKW(bAyO4#9UZjiR%yxQSUH$!`^l831F0`E_?Vmt60Z;C;3!VRT~@ZE zJNLvf;!#Ajb9`6k7rFLfRNHEL!|WGSLCxML3B#R_-aoz>Sll7G6ENdH@doqmQNGN! zwC}0L9~A!R#SE&s{fU(XGLps9Bs>BID`}Y3&QX}7*I|yD{c-+ zfEkU~Ot&nbB-1Syq=}V(Q(Nx+=pG{lqGEWFz;4O!5nFj>^8#*dRqh}&RUxApe%nmh zR(zf%HcG{#7CgG3?U`$go-b~jUMUyJ8E)9Wn<>f6Y_O9_7lb>l5*QnBSjn<|KS_!A z3+cX>%_Ps<-l1vS`LfZ!{OWGT*-$LiFjq78_4;9?_x(8~1Wn+Vy1@wud}AK$uXi2y zq7Rfg#Tvz3sdg!iLMn3E0TvmB4 z8Kbq1K96i4Gw>b1rHNI#Y39GBq}pcB1q)Ioee;=@OZNKdVAa+6Zz~)iCQgarLUAX4 z!F`q#fGkyd#|ZQ{j&Boak&e#{?%PSf``omK+iH3t{;`n{aDM~$iY_V zQ?m~RxZu)0=~E=XJX1`{OD^wzpSm=!9Jls@Mb0dUB_YS@Tx7@eteRus2>c!WcA9ple3x{D+ zuIZei%BK7jWMadks0h}+quRw_l&cZ-l;V2Cusq`OyQzqZ)?A2FQJIuWMA;>nR4Li@ z?i(31Wz-t&)HA2OE!Wg#i+B4wSmXqo{S8(`xy(~3tEXs{%V$i3*WpeF9fuOL>&F1aK$2o_cL%r%>NjR@5?$OL~R@&|G(DX29L^R(R zQ(zfjsCy&6#4kw0n=oc{%_Dit$b%vVsHe5RJ(HXv#HkQ_ttBQaIP^hX4Y>62Jrb(v zk>=;2{Gave4Q^;y#^<Cx0aX2+KyJW6;GG+XIVYX;%bLJ zd?*WbzH)1>FDyb{aj+gDHP>&9^2@)j=*wCz)1k%h-lf(Bdl&RR$2IVU?|RYgy-w)1 zt&Zx7L_y(*JMuz4GI&nhiyugqk*2Euw+86)1%qxzaKLA4p)v=`G}=sv$+@~y7I59V zdygJ?)c1s9aKj;AD^+N=d^dHdYwmyN9x@s}Kcpo`US`)isXJm?%dOw}@t$dJtNrEd z8Iu*GB!0+e`nTw3mIYN#2K3_P)>7(i)E=j4L@exBn<(AF^G2llMZeU(ufWv?IyWk9 zGuL#ct}UFh`~2!gkZv>Fq%diqv~bXN)Xij&NAis(-U1t{vUrB3uOB1>*~eX z)E*a$RrC54d_3s(&9j zkrz-$-h*9XzQXIpM*^Zc%#U9TJHOsEWm)XE-3r@a6kU=QMfE)#4WY4Mu`I(1OP4r( z9c0@XDRvs~+ng-Ugmi85viTtGd#^~}AGh#i4iOxtO|s&LlZ@7cyDG`6;CF#d`7IpGc=i_7tKdJhd#nw=vs$%Fl0`1%KN2U;h!3AX*qh=Ngy_LGm$N2vLam25Md4eM9wz zDiWL@l<7R&?Y)3|Jo0cqp)hm%)~#i=q={S0f=bU7J2_H=C4B{!A$o!n{LOa7q7j#_ zh^A{I^O@Kq`;e}xK6Val$i*o0uA3~SwXoD#e{vS{ybf*8a4EkfsRXCEkuJOXP9FEw zyI%(`n({L9KK)v5F0OMk&Yp#;XVSw;^H613YX z4M`kKjIYJxM--lbVY0RIbX|Df>AI0s>Sm}<@lrfn&Kccs z;>I>JPIsLedMDXgJoWv2Ax`gERAXX+LENFT>Zfym`CT=@&}MX#>0OqW`jGjlhI2bB z(Bui&Ncg=_L4e-Sv&wuI!5|}$RAo8~oX#CA3cEQLwKEywbg6g32Y+m!xkM;(5=s1f+M}LnS=7w^(aX$tvD$21+=YO*$?wXP7IA z6|I+if7pkj#Q3!>G>CagE{0EbBI;dxUzaB5M5Rk7d2u5?LinsN`i%??rIb3{#xIDu z{Wat{cVk@gzD3)-`(AgS$^BvZ)Xz2Zi?QX;B`6ynR@58xA2vmfAAbL_eXz2)JTn{r zJ~?D>o$A05V@vsrYj=6SFMVky8Slq0$zGusOmX4M1hbXwvIffF2B}5QgS)X5>@(D- z1~9IV_B21c$=|&aJU|}2uOO~@V39oi=$VpZxzpW^JongUHoBEhdK}=-q-s9!nj>fS zNSEhI<83@_uOi!a&>8|P>TrtgC-?5&+jW8zPOx$ZWY!v*u+AS?T7Qf@T5exOfB!=3 zYt#Oc+cE)f<@=*6%8%yjX&K+@l`Ct{a2xDDID%vOd|6wM67a(gKPo7CRex}u?e$0u zEoWbP5@x~eH9G~L)L@WdefXT)mut;{<}l>y5kqr4y$tp%o8wwg3;t}_YX9brV`;ff z?R;Tt)Y{OYWtl@V-cqDqV2vg0NNCMDj8`82Y0Y3Q2{)C8x1(W=$M0Q#?ll_mlKW0N zj+5Rh5g(3A=C0>jQw(c}#|PqC=(9X0vj=?LRIC>U zlP+P})vn374DHXY@2=hZ5Op(fNJBpjh7ZOqN4JM9)3Zgl@l(jALt#=E|w@)YF zJn3N!o0y9E(S%N^U(#J45cR8UKyFg9zo>HH8V|@+YPm9ttPwvdVZU~ zbSzAOODOp^FX+9Gm2=T+ZEI&iAu4OlJmrsgw>%s-J<}IA-D^S>6J%iOdNMYd3eRjJk* zT6?D|CMcJ72R5jv&^L56@zbNS6H)xldKZ#_773dz>7!o#IbLq@xK5)VOkrYUk0Y*f zk3F8+qK`o4+@8z{t4U#qzNqhH{Uqw5lep!iJNq@J=2H5X&lbPD(!C-1Xpq51c5;Be z-F$}LX2i=d8)iP!+$`Yy1o(cjQNUT;)H(pCyXykF9=^-z9=qBW>um(mYnKv;QfW26 zI!j#@el4t}DCJi7^)hGi?r>OnxAluC6T4cDvmxdyOt3(&-8;#zN1}r)yoLb{ua~Y| zn{L-=Ftn9?k7^B|2XoQ5-jN(mU6Hq{qkivIoez9&yjo`mJ5 za@}X2fXzD&YKXgU&=&QDbjX!V&4|0gd@T83XYt z_ZMRTi-9Fhp8F;Kd>#f7AL##o5Y8gD$E5{8-M%XIAbK>r%f86~ItI3dendES-DzZsSXj$E{B4oNnunczLDYWZr&B)&h%&s4lY$f;v4-ObS zC3cLs5=NX0+N&W`9N(_QX`_qBoJ)L+-ui2kk;HjEe~$z=t?Yj&{Ww~9&~!O6#6a{s z-?fFB!Lj-+usnVIP7z1L_Ls~LhaC0Lh?sUvn|548^T0N}1&W8kJq@Z8ZNvHgg<5#cBxFg9qUD;9+&B93FKqXl;+AR3sV zg0Z2RfCAz!+{j&@089R9SAshuoxA~jKbru=HvXTDPH=ky6%qO8O8K7TxD(Pw&c)sd0RSHNlf&2$X^@17__0Y`AJG;R0Yi=j7~E9_ zfwXrZ03*UM$C5r4;cNsT;1l8wh=$6ELEIq$ydXpXL^ks~t09uAKfUpD1b1ufF{Lsf z&>*6xj#YU$264>1{x{Dc(HJbu0ggU#fCl`R4FXCWkMM7I1C9govlJ9v2nZVKVh<2D zM!LwkV2~%maX(|EE!F|^3x*Nv=i~*JAiy!g2M7=c6ZZ#(p0q&0P{7IOMEmm$6(>?N zs06WmfdGgY1Ry3xRDQl75HWx_A!H{u@eDmquHTja`?myP%wt$bfNm&57bKCk1BkbV z-^1}|auN~Y&zw_7+7fq9T#4R4*w39v41Z&9px+^*4jN_aZbKmad^T_-8U+9efgnPJ zrSmypv96NB1e!@u?a^>o2c!)~2!*!i|Czur0{_P%Q7#HZ63V9_DMH9wAVdTT5&?+< zfdW7sl>Kqwj<@iOYyLM4^+F@;D1iWwC?)Wp0|13Uzz~2P z;FkskiV=cBJOC~y8c;%nFx`J>;vho6{zC(T2+a3CG%*Q+fBvmOpkjn5{96NoAb<1~ zl@R}9Ef63vd;i^+05JdP3lRnW(H9C5{bL_c5n}3|jE6aB)7YYV}DY>~7wUsFU3+#SSo&W#< diff --git a/tex/figures/mcfg/mcfg.svg b/tex/figures/mcfg/mcfg.svg deleted file mode 100644 index 8cd991c..0000000 --- a/tex/figures/mcfg/mcfg.svg +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - CFL - TAG - 2-MCFL - 3-MCFL - m-MCFL - (m+1)-MCFL - - - diff --git a/tex/figures/mcfg/mcfg_2.pdf b/tex/figures/mcfg/mcfg_2.pdf deleted file mode 100644 index bc1933f653d4a2681d6d373476d7442cdf05d5b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6053 zcmbVQ2{@GN+dobYH7S)POBl(%%w`6WC5%1$nx!$u7-2L^_9cuKTe4&=SrS=8LQ#@! zEZLQiB4jB_vzyz2N-oQ4m?QgqCl&ojh*9>Rt5f!A4*cIX00VVOO5e$06!i~(e4p!*`?7t>i}iii%Pb*Qxy3)r z;|uB<)g-1A7%0KYobvUN51NuVwAmxD8K z-34D4?}${eO6&ewH;C=y_7v&=0*+vwYa=slo$#wNXKSKVe{H&?>A={R&$LsLD za>d1osPTl*3?v$5-Eabh)L&~AFw&jXX?B7g@$0}o-ROW+b3^j2>Q8Z%cs&rhDRjf7 zIGhXorDdL}s4R$;#pl_UNl@zZe$&+Y#%k~LAuiH7;ERvSxw{aboKFdUVVrAE8nntn z)e!cjk`G=}6b0*^D+_!+k`Wz@G*cYO;j)4pcCO6yoqzZKW*=3CEJr;LYG2y2kU#UX zDKzWdC_lF&GWxRgoG!cB5Zm1`Ptt&)Umbo~L8+?d;rRBap4-FrMYW?2UEe&`Jxd0z zN#ELve}PE&TgG~3TvKA*ELDrsbtuZ_)Z1D&6T`TK2&Tu=DE*Wr#e!T`^^o*}1Fwav z;0m{mOW&d$hOj!DPn`tJhkb^3>)`W(q z=SjzwP9C_Y7N*)9s(Nh@c|IioT(%wMTB2m@5X@58a6OtveTMWq94rF8Zvu3JC zb8r~3%ypbQW@&NxC`E1HJ=jB|(m;Y(t>)!imp-iWDdyYSP=3*Q^0~eSh9ZiQ;sYsJ1P zLIXtG2nqLlZkoFDskgl8@9K}`7}xdk>9LzmI88Pe%A3sxa7E+mY@B#hL!u$I?9alt zUYj|n#0_;zrs#_!-Fmm;Wo1RvwLN)0-aw=plr3*N;XGL-tZ6*sR{Zs&KowrlX2{m^Q6 zw4B4deX*em82gEB?oi|V}f2i93wIFF_kW`o08(@CEhs)kC zab3jxu_^nrX)1*Z=1tLa`Q*vm?pU$^cAu;GBOac%jDdCp4x-N1?W)_aWgVwe3G)r- z7r4S7-u^&O!~l}ER6Qm;>apbOb2rrdu%Lv097-cKOF9K^vCIYO542GcYM;Uylzrmy z>2E3*E$2Z~$Q2gYUTe9Fm#Rwyk*5UJSz9QB9TsR8vQ`$2a&E z&5Shlt2MLB_GyNDV$wL0Gc5{^CFl0#b5_j6yDdP+hhD2DztucVkC;r@OREOcR@uxkg4k7j38Krsg~YeU_;O>Rmc{Iy?*L zxeKweNEy)_EGspJ{8hD~WjkSD##ejz$T>CgfW)NT_flVjLiX8)Z1TWF+Zrw=->dKH zOo;D#7p`!;@%pf1bdu!dn4BTMOzh$vE0^F-_qX{M&rgeggO{;04UYGhoN><`96d^W zbQn1_SUMI!rkroI*8jVxTel{3fx0FFFUnK=?w7o5b^lZ`NaCc?sjOfUn;zOzy@=$r zDP@h!E9H4ePM??v%SjJ#_|jB_dvvCEqyZW-BU#w^QABa#OQu0*58~=D@QDFCnk)}W zWJI^#KOuavvt?{T_{CInlK)F;v6I&mq^EaDrWC5%@yz^2WT1_Gk)p#xYs*S!cl8Ui z#3B9p(Feu@MR~E7bw{wuwWrRJOO!{110;sp9Q{i*U0zo(ZN{q|;w0vabH_`#bvzzQ z(XcXY$}0lLN6&RELMFwe7K9FK3fT-uEcMtyJ9%GZYn1w`wFNq`d%+RYed8%jlrBm@ zZ}SGH#$wJ^W)xUi{bqY%Q_}U%9GAD5qm$C)y$ZBo(D15dLIpCs1pd0@ayw64jXH<@ zmKBHpCG)h}%LY&RVtFr|cy$8XQcfLE5riCgcFWF0^me>&EHP$Q!7mgWaqbY0LSagY zNRuK;_tNDAMl@A7r_|+bf;)n~6;yMMg)-WpB zhKX@e30t~VvbcbddvSL%L}zrMJ`icRv`)b}n>1Uk*<&-uW^c{hTJNeobzDFYR3nP# znus~(6YKBvkwT2+pM`LX9OEsote!9COeHugEw)zU3aOTl4L0??8JYfm5t{{oU)i&XK^6ljh^29!+&16d5ZE_lCaee8lRW=cZf+x55-yM4M zDp}}6SUO+sTiXAa0`(k74Z2=5l66pE;*~dhZnQx8azd8Y!RW#$?zBjC4@)ZVFtfsU z^Nw54%!NNknFUHi-Q&lIv6^$TzzVDM4~6%wi1EvgmMBYEs<~6MDR*;bfKiu@-K;?t$mv21NH;4KO z5_!r)%M%m9lYCwEO`td*ziFn5rPkHn5Rr5Z$OQQIR7mdw)A%mIM95k1hW#%auz?|g z+IJtw%?_+A#}`}9POeV-Ry4oRBRqOXb!R+x(W92vB+uG5)Ae+CXKX0jmdmi(ZBKp! zQbI)-I-4?+7wbC68DpjTu$;&JByl8R5~n!umr~H3tn!3HMUj3Z#WSpSyjnFHisP>L zQp=ezZzVeRDcA@PeV3u0?p(m`tv~+Rt9(7KFDx=<0P_ z;^Hn4o-2L!fv*eYo5=HkBj$pj^0AAnECF|wqi66wfAr+t!Qffz(E03=Tz*gb!*VWC zSEe(sD-Y!I!mQV(!6*BDv{Rd}NlY_VVnjsIJmUS1`_A*+F}SykEL9F0#U4OPXNlMZ zE2T7L@tjs=7H4C~$Lbt?df(qCZuDKAgLB)eW8CGq4z%o{4Bc;fYj7Vif7l6#zR9Ga z1W)`Y7T1x_+ZhWl#BmD=x!A*7hE6Fx+6PT=uWL^hR^{fB0NCZF4E@9P7Z1;jL{fuX zmk6ISZgq>}Ud%(X@Opf(0NG^`gE3T+BVxHJGP;eDz?5@4Xgrs>$GP2LXzE>(aY>g# z4RE=?rJvtjrdD3m$A&aE5bqk@;5kb#ZAws@@6~Ps zS2D7`vJx5!9Vhn}%GyjNt%+|M3``ZUc)GdemTet79bpD&^{#FU5L#zo?}7B(^Sl!i z-&GJyzHW<zoH=x0@45Y9{ z&Hdl=7kwC%CF|joQK#{l1f3<?OyvchS0#=trJdEo zKfN1O2Eg`Le@u2ti+(9i@nRpb@YWm4u1^Kv#l9BSAE1l_nr!8(J0xQyWCavtQaPee z6y4N{9&dL2wg`H*J_onbwe+6EULP=8$lYRG*=N=S05VFM%079ZBqZzAu zV)%yA30i+XR{R{o(JAS6aBu=a3FbS$nN!H1v|gaD?8SVC{2nXl_Qv1V!+6lvK~PSh z=~JKYH<-P(!xi7V+mXjp+3##mU)U_KH)KW&y?p1*iul?fBImuxw!Lzp(O0FvG`HWU zw4Wj%S&&C;fdj}gN;xGqsDzN>$(FY^o7rdGrSB|e-IucH_bxR-QR)fIiJGW94n20x zt44hFnMXLojdDs<$BNnc4VxS!+K3!2K5>gl_3v!jP?;vE#~}`=#Cm-S_g_i;^;yOb zjJ&N-`DZuTA4;*JZg8mF(7UP9+UP{NYPGDcDHieS)L49+FDjFnm9wdtnM2oo;~?b# ztNa8bg*oks!@V%9F8hrpMa(6Z#@xXPZ_&m#5R0+eKN=aqHe>eNPpjm@GRL3fGAdJQ zIFQ2=iCIcd9)fK~CXi#=HBu|98t81kzW_q);gfzJ7mqAmRlw9Tzg%)7B(eD*KCU67 z`QE6zL(iig9I{q-gHodf5iA|$%`eV5*?`4(_bsfnUI~1s@LYOf#W9%IYh}Gvab7J5 zwB_Ue$U*igV#U1KXo@Y0)R;VvOcBTvTyft2?3;F}Q1Y3if}8AT9giMM(l(l!&{Fb~ zuosMWxS^+75TYfBe9?aJ9YCgWMk1t)vnx=Zea`q&chQko53@d8FfBQaG6pY0%RfliP@4S-EY<}=c z7!(5E<9Z6eb07$v#Qopo5xZEb$4lT5&2|4*QazesQCUi-s3r*>Pp8z$Ul_O=51T|C zZ9Morfcct9-odu94%>@Q7B7D3wqXkn+OQ^bT>xA7*?#Ji4CB{ATZ^mma?Izhn8%SK zWdU6*~2R} zmeV62!=A_ajJoEhmi*naHt@MZfiboN!>`lMb6k|e7pLV!HkLJFRe$+wbS`MpWO)vTOd${@S*fqLTtJ0ilO&626^p{6vac8_Ht?TegH}PR@pG#BZ`& zuTyax2D;08=`>vfLqrpBo+LbhPGfhN`#F?5jfU%MTbWv_OKM55BAU+l6`=AvCVhT%TN(<3?>N*^p4u23)`cbt(7M@inUXN>7C>64^a$vN z_MSnHkVdXCP#~Ru|H{YdYQ*o^*zJMrNZL^%%xH|Co~a%0Srieoqig)P%-{$_lDZ3u zu$KUR)DIg1k=^OxpXmnfEXXeOH9crzAkG5|1XT=LKxhvbC=a8@2SeP6BT#haU?cH#=98jLNSbO&W@2wz5 z*IjmRSz53=q6|%3!JB*F=-MZcejNO|B)Y%Lqi_T~5F!JC%h2|Qm0p;m}Llb521g!Wjh}CIo zED4AA(4Z?`Vj8ERH0*-mPy_@j3j@O?!7x!USp3&P|09>}DOl<#8mjTwoyFS;;fH?p zAJxm7fN=(Zfiz%%e_lWY91ep6oq<1ma9KDl9{L6J*z?rA`IA07sSM=>|g2&SqeOFzh+d3Z3w6)#A#jZkzB9L~n3rEPy0fdD$ I4UvHV0mU){?EnA( diff --git a/tex/figures/mcfg/mcfg_2.svg b/tex/figures/mcfg/mcfg_2.svg deleted file mode 100644 index 43b494b..0000000 --- a/tex/figures/mcfg/mcfg_2.svg +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - m-MCFL(1) - m-MCFL(2) - m-MCFL(r) - m-MCFL(r+1) - m-MCFL - - - - diff --git a/tex/figures/multi/graph0.tex b/tex/figures/multi/graph0.tex deleted file mode 100644 index 9f1a442..0000000 --- a/tex/figures/multi/graph0.tex +++ /dev/null @@ -1,18 +0,0 @@ -\begin{tikzpicture}[node distance=2cm, shorten >=1pt,on grid,auto] - \node[state] (q_0) {$0$}; - \node[state] (q_1) [right=of q_0] {$1$}; - \node[state] (q_2) [right=of q_1] {$2$}; - \node[state] (q_6) [below=of q_2] {$6$}; - \node[state] (q_3) [right=of q_2] {$3$}; - \node[state] (q_5) [right=of q_6] {$5$}; - \node[state] (q_4) [right=of q_3] {$4$}; - - \path[->] - (q_0) edge node {a} (q_1) - (q_1) edge node {b} (q_2) - (q_1) edge node {a} (q_6) - (q_2) edge node {c} (q_3) - (q_3) edge node {c} (q_4) - (q_6) edge node {b} (q_5) - (q_5) edge node {c} (q_4); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph0.tex b/tex/figures/tensor/graph0.tex deleted file mode 100644 index 1107ee5..0000000 --- a/tex/figures/tensor/graph0.tex +++ /dev/null @@ -1,20 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge[left] node {a} (q_1) - (q_1) edge[above] node {a} (q_2) - edge[bend left, above] node {\textbf{S}} (q_3) - (q_2) edge[below] node {a} (q_0) - edge[bend left, above] node {b} (q_3) - (q_3) edge[bend left, below] node {b} (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph1.tex b/tex/figures/tensor/graph1.tex deleted file mode 100644 index 678bc8e..0000000 --- a/tex/figures/tensor/graph1.tex +++ /dev/null @@ -1,21 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge[left] node {a} (q_1) - edge[bend right, below] node {\textbf{S}} (q_2) - (q_1) edge[above] node {a} (q_2) - edge[bend left, above] node {S} (q_3) - (q_2) edge[below] node {a} (q_0) - edge[bend left, above] node {b} (q_3) - (q_3) edge[bend left, below] node {b} (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph2.tex b/tex/figures/tensor/graph2.tex deleted file mode 100644 index 4965a0f..0000000 --- a/tex/figures/tensor/graph2.tex +++ /dev/null @@ -1,21 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge[left] node {a} (q_1) - edge[bend right, below] node {S} (q_2) - (q_1) edge[above] node {a} (q_2) - edge[bend left, above, out=30, in=135] node {S} (q_3) - (q_2) edge[below] node {a} (q_0) - edge[bend left, above] node {b, \textbf{S}} (q_3) - (q_3) edge[bend left, below] node {b} (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph3.tex b/tex/figures/tensor/graph3.tex deleted file mode 100644 index cb1ad3e..0000000 --- a/tex/figures/tensor/graph3.tex +++ /dev/null @@ -1,21 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge[left] node {a} (q_1) - edge[bend right, below] node {S} (q_2) - (q_1) edge[above] node {a, \textbf{S}} (q_2) - edge[bend left, above, out=30, in=135] node {S} (q_3) - (q_2) edge[below] node {a} (q_0) - edge[bend left, above] node {b, S} (q_3) - (q_3) edge[bend left, below] node {b} (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph4.tex b/tex/figures/tensor/graph4.tex deleted file mode 100644 index a674ced..0000000 --- a/tex/figures/tensor/graph4.tex +++ /dev/null @@ -1,22 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge[left] node {a} (q_1) - edge[bend right, below] node {S} (q_2) - edge[bend right, below, out=330, in=225] node {\textbf{S}} (q_3) - (q_1) edge[above] node {a, S} (q_2) - edge[bend left, above, out=30, in=135] node {S} (q_3) - (q_2) edge[below] node {a} (q_0) - edge[bend left, above] node {b, S} (q_3) - (q_3) edge[bend left, below] node {b} (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph5.tex b/tex/figures/tensor/graph5.tex deleted file mode 100644 index dc0b0b1..0000000 --- a/tex/figures/tensor/graph5.tex +++ /dev/null @@ -1,23 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \node[state] (q_3) [right=1.5cm of q_2] {$3$}; - \path[->] - (q_0) edge[left] node {a} (q_1) - edge[bend right, below] node {S} (q_2) - edge[bend right, below, out=330, in=225] node {S} (q_3) - (q_1) edge[above] node {a, S} (q_2) - edge[bend left, above, out=30, in=135] node {S} (q_3) - (q_2) edge[below] node {a} (q_0) - edge[bend left, above] node {b, S} (q_3) - edge[loop right] node {\textbf{S}} () - (q_3) edge[bend left, below] node {b} (q_2); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/recursive.tex b/tex/figures/tensor/recursive.tex deleted file mode 100644 index 36015c3..0000000 --- a/tex/figures/tensor/recursive.tex +++ /dev/null @@ -1,16 +0,0 @@ -\begin{tikzpicture}[] - % Apex angle 60 degrees - \node[isosceles triangle, - isosceles triangle apex angle=60, - draw=none,fill=none, - minimum size=2cm] (T60) at (3,0){}; - - - \node[state, initial, accepting] (q_0) at (T60.right corner) {$0$}; - \node[state] (q_1) at (T60.left corner) {$1$}; - \node[state] (q_2) at (T60.apex) {$2$}; - \path[->] - (q_0) edge[left] node {a} (q_1) - (q_1) edge[above] node {S} (q_2) - (q_2) edge[below] node {b} (q_0); -\end{tikzpicture} \ No newline at end of file diff --git a/tex/makefile b/tex/makefile deleted file mode 100644 index d3704b4..0000000 --- a/tex/makefile +++ /dev/null @@ -1,9 +0,0 @@ -main=FormalLanguageConstrainedReachabilityLectureNotes - -all: - pdflatex $(main).tex - bibtex $(main).aux - pdflatex $(main).tex - pdflatex $(main).tex -clean: - rm -f $(main).pdf *.log *.aux *.bbl *.blg *.out *.toc *~ From f02a696322f526f3b8288fc21b658a48bd7c05de Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sat, 8 Jun 2024 13:54:32 +0300 Subject: [PATCH 02/29] Add VS Code settings --- .vscode/extensions.json | 5 +++++ .vscode/settings.json | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..d9e6a8a --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "james-yu.latex-workshop" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c6e97ba --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,28 @@ +{ + "latex-workshop.latex.recipes": [ + { + "name": "latexmk (lualatex)", + "tools": [ + "lualatexmk" + ] + }, + ], + "files.exclude": { + "**/**.aux": true, + "**/**.bbl": true, + "**/**.bcf": true, + "**/**.blg": true, + "**/**.fdb_latexmk": true, + "**/**.fls": true, + "**/**.log": true, + "**/**.out": true, + "**/**.run.xml": true, + "**/**.synctex.gz": true, + "**/**.synctex(busy)": true, + "**/**.toc": true + }, + "editor.formatOnSave": true, + "files.insertFinalNewline": true, + "files.trimFinalNewlines": true, + "files.trimTrailingWhitespace": true, +} From e83df65222c51ec3af722834d91e32a3f60c5ee8 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sat, 8 Jun 2024 13:58:03 +0300 Subject: [PATCH 03/29] Init new version of main file Based on https://github.com/fmarotta/kaobook/commit/81bfb18af4a13dc38a82ebf233c4f62ab7699245 --- tex/kao.sty | 1427 +++++++++++++++++++++++++++++++++++++++ tex/kaobook.cls | 282 ++++++++ tex/main.pdf | Bin 0 -> 13399 bytes tex/main.tex | 21 + tex/styles/language.tex | 3 + 5 files changed, 1733 insertions(+) create mode 100644 tex/kao.sty create mode 100644 tex/kaobook.cls create mode 100644 tex/main.pdf create mode 100644 tex/main.tex create mode 100644 tex/styles/language.tex diff --git a/tex/kao.sty b/tex/kao.sty new file mode 100644 index 0000000..54174be --- /dev/null +++ b/tex/kao.sty @@ -0,0 +1,1427 @@ +\ProvidesPackage{kao} + +%---------------------------------------------------------------------------------------- +% DECLARE KAO +%---------------------------------------------------------------------------------------- + +\DefineFamily{kao}% Define the family name +\DefineFamilyMember{kao}% Add a member to the family +\DefineFamilyKey{kao}{secnumdepth}[1]{\setcounter{secnumdepth}{#1}\FamilyKeyStateProcessed}% Define a key and a default value +\FamilyProcessOptions{kao}% Process the options + +%---------------------------------------------------------------------------------------- +% USEFUL PACKAGES AND COMMANDS +%---------------------------------------------------------------------------------------- + +\RequirePackage{kvoptions} % Handle package options +\RequirePackage{etoolbox} % Easy programming to modify TeX stuff +\RequirePackage{calc} % Make calculations +\RequirePackage[usenames,dvipsnames,table]{xcolor} % Colours +\RequirePackage{iftex} % Check whether XeTeX is being used +\RequirePackage{xifthen} % Easy conditionals +\RequirePackage{options} % Manage class options +\RequirePackage{xparse} % Parse arguments for macros +\RequirePackage{xpatch} % Patch LaTeX code in external packages +\RequirePackage{xstring} % Parse strings +\RequirePackage{afterpage} % Run commands after specific pages +\RequirePackage{imakeidx} % For the index; must be loaded before the 'caption' and 'hyperref' packages +\RequirePackage{varioref} % For the cross-references; must be loaded before the 'hyperref' and 'cleveref' packages +\AtEndPreamble{\RequirePackage{scrhack}} % Make some packages compatible with KOMAScript + +% Define \Ifthispageodd (with a capital 'i') to make kaobook compatible with older KOMAScript versions +\@ifpackagelater{scrbase}{2019/12/22}{% +}{% + \let\Ifthispageodd\ifthispageodd% +} + +%---------------------------------------------------------------------------------------- +% KAO-SPECIFIC OPTIONS +%---------------------------------------------------------------------------------------- + +% Set up the package options +\SetupKeyvalOptions{ + family = kao, + prefix = kao@ +} + +% https://tex.stackexchange.com/questions/47576/combining-ifxetex-and-ifluatex-with-the-logical-or-operation +% Introduce a command to find out whether the compiler is XeTeX or LuaTeX +\newif\ifxetexorluatex +\ifxetex + \xetexorluatextrue +\else + \ifluatex + \xetexorluatextrue + \else + \xetexorluatexfalse + \fi +\fi + +\ifxetexorluatex + \newcommand{\kao@defaultfontmethod}{modern} +\else + \newcommand{\kao@defaultfontmethod}{tex} +\fi + +% Set default based on rendering engine +\DeclareStringOption[\kao@defaultfontmethod]{fontmethod} + +\ProcessKeyvalOptions{kao} + +%---------------------------------------------------------------------------------------- +% TITLE AND AUTHOR MACROS +%---------------------------------------------------------------------------------------- + +% Provide an optional argument to the \title command in which to store a plain text title, without any formatting +% Usage: \title[Plain Title]{Actual Title} +\newcommand{\@plaintitle}{} +\renewcommand{\title}[2][]{% + \gdef\@title{#2} % Store the full title in @title + \ifthenelse{\isempty{#1}}{ % If there is no plain title + \renewcommand{\@plaintitle}{\@title} % Use full title + }{ % If there is a plain title + \renewcommand{\@plaintitle}{#1} % Use provided plain-text title + }% + \hypersetup{pdftitle={\@plaintitle}} % Set the PDF metadata title +} + +% Provide an optional argument to the \author command in which to store a plain text author, without any formatting +% Usage: \author[Plain Author]{Actual Author} +\newcommand{\@plainauthor}{} +\renewcommand{\author}[2][]{% + \gdef\@author{#2} % Store the full author in @author + \ifthenelse{\isempty{#1}}{ % If there is no plain author + \renewcommand{\@plainauthor}{\@author}% Use full author + }{ % If there is a plain author + \renewcommand{\@plainauthor}{#1}% Use provided plain-text author + }% + \hypersetup{pdfauthor={\@plainauthor}} % Set the PDF metadata author +} + +% Make a bookmark to the title page +\pretocmd{\maketitle}{\pdfbookmark[1]{\@plaintitle}{title}}{}{}% + +%---------------------------------------------------------------------------------------- +% PAGE LAYOUT +%---------------------------------------------------------------------------------------- + +% Define lengths to set the scale of the document. Changing these +% lengths should affect all the other pagesize-dependent elements in the +% layout, such as the geometry of the page, the spacing between +% paragraphs, and so on. (As of now, not all the elements rely on hscale +% and vscale; future work will address this shortcoming.) +\newlength{\hscale} +\newlength{\vscale} + +% By default, the scales are set to work for a4paper +\setlength{\hscale}{1mm} +\setlength{\vscale}{1mm} + +% Define hscale and vscale for all types of paper +\@ifclasswith{\@baseclass}{a0paper}{\setlength{\hscale}{4mm}\setlength{\vscale}{4mm}}{} +\@ifclasswith{\@baseclass}{a1paper}{\setlength{\hscale}{2.828mm}\setlength{\vscale}{2.828mm}}{} +\@ifclasswith{\@baseclass}{a2paper}{\setlength{\hscale}{2mm}\setlength{\vscale}{2mm}}{} +\@ifclasswith{\@baseclass}{a3paper}{\setlength{\hscale}{1.414mm}\setlength{\vscale}{1.414mm}}{} +\@ifclasswith{\@baseclass}{a4paper}{\setlength{\hscale}{1mm}\setlength{\vscale}{1mm}}{} +\@ifclasswith{\@baseclass}{a5paper}{\setlength{\hscale}{0.704mm}\setlength{\vscale}{0.704mm}}{} +\@ifclasswith{\@baseclass}{a6paper}{\setlength{\hscale}{0.5mm}\setlength{\vscale}{0.5mm}}{} +\@ifclasswith{\@baseclass}{b0paper}{\setlength{\hscale}{4.761mm}\setlength{\vscale}{4.761mm}}{} +\@ifclasswith{\@baseclass}{b1paper}{\setlength{\hscale}{3.367mm}\setlength{\vscale}{3.367mm}}{} +\@ifclasswith{\@baseclass}{b2paper}{\setlength{\hscale}{2.380mm}\setlength{\vscale}{2.380mm}}{} +\@ifclasswith{\@baseclass}{b3paper}{\setlength{\hscale}{1.681mm}\setlength{\vscale}{1.681mm}}{} +\@ifclasswith{\@baseclass}{b4paper}{\setlength{\hscale}{1.190mm}\setlength{\vscale}{1.190mm}}{} +\@ifclasswith{\@baseclass}{b5paper}{\setlength{\hscale}{0.837mm}\setlength{\vscale}{0.837mm}}{} +\@ifclasswith{\@baseclass}{b6paper}{\setlength{\hscale}{0.570mm}\setlength{\vscale}{0.570mm}}{} +\@ifclasswith{\@baseclass}{c0paper}{\setlength{\hscale}{4.367mm}\setlength{\vscale}{4.367mm}}{} +\@ifclasswith{\@baseclass}{c1paper}{\setlength{\hscale}{3.085mm}\setlength{\vscale}{3.085mm}}{} +\@ifclasswith{\@baseclass}{c2paper}{\setlength{\hscale}{2.180mm}\setlength{\vscale}{2.180mm}}{} +\@ifclasswith{\@baseclass}{c3paper}{\setlength{\hscale}{1.542mm}\setlength{\vscale}{1.542mm}}{} +\@ifclasswith{\@baseclass}{c4paper}{\setlength{\hscale}{1.090mm}\setlength{\vscale}{1.090mm}}{} +\@ifclasswith{\@baseclass}{c5paper}{\setlength{\hscale}{0.771mm}\setlength{\vscale}{0.771mm}}{} +\@ifclasswith{\@baseclass}{c6paper}{\setlength{\hscale}{0.542mm}\setlength{\vscale}{0.542mm}}{} +\@ifclasswith{\@baseclass}{b0j}{\setlength{\hscale}{4.904mm}\setlength{\vscale}{4.904mm}}{} +\@ifclasswith{\@baseclass}{b1j}{\setlength{\hscale}{3.467mm}\setlength{\vscale}{3.467mm}}{} +\@ifclasswith{\@baseclass}{b2j}{\setlength{\hscale}{2.452mm}\setlength{\vscale}{2.452mm}}{} +\@ifclasswith{\@baseclass}{b3j}{\setlength{\hscale}{1.733mm}\setlength{\vscale}{1.733mm}}{} +\@ifclasswith{\@baseclass}{b4j}{\setlength{\hscale}{1.226mm}\setlength{\vscale}{1.226mm}}{} +\@ifclasswith{\@baseclass}{b5j}{\setlength{\hscale}{0.867mm}\setlength{\vscale}{0.867mm}}{} +\@ifclasswith{\@baseclass}{b6j}{\setlength{\hscale}{0.613mm}\setlength{\vscale}{0.613mm}}{} +\@ifclasswith{\@baseclass}{ansiapaper}{\setlength{\hscale}{1.028mm}\setlength{\vscale}{0.939mm}}{} +\@ifclasswith{\@baseclass}{ansibpaper}{\setlength{\hscale}{1.328mm}\setlength{\vscale}{1.454mm}}{} +\@ifclasswith{\@baseclass}{ansicpaper}{\setlength{\hscale}{2.057mm}\setlength{\vscale}{1.882mm}}{} +\@ifclasswith{\@baseclass}{ansidpaper}{\setlength{\hscale}{2.662mm}\setlength{\vscale}{2.909mm}}{} +\@ifclasswith{\@baseclass}{ansiepaper}{\setlength{\hscale}{4.114mm}\setlength{\vscale}{3.764mm}}{} +\@ifclasswith{\@baseclass}{letterpaper}{\setlength{\hscale}{1.028mm}\setlength{\vscale}{0.939mm}}{} +\@ifclasswith{\@baseclass}{executivepaper}{\setlength{\hscale}{0.876mm}\setlength{\vscale}{0.898mm}}{} +\@ifclasswith{\@baseclass}{legalpaper}{\setlength{\hscale}{1.028mm}\setlength{\vscale}{1.198mm}}{} +\@ifclasswith{\@baseclass}{smallpocketpaper}{\setlength{\hscale}{0.571mm}\setlength{\vscale}{0.639mm}}{} +\@ifclasswith{\@baseclass}{pocketpaper}{\setlength{\hscale}{0.642mm}\setlength{\vscale}{0.723mm}}{} +\@ifclasswith{\@baseclass}{juvenilepaper}{\setlength{\hscale}{0.738mm}\setlength{\vscale}{0.740mm}}{} +\@ifclasswith{\@baseclass}{smallphotopaper}{\setlength{\hscale}{0.809mm}\setlength{\vscale}{0.572mm}}{} +\@ifclasswith{\@baseclass}{photopaper}{\setlength{\hscale}{1.00mm}\setlength{\vscale}{0.707mm}}{} +\@ifclasswith{\@baseclass}{appendixpaper}{\setlength{\hscale}{1.000mm}\setlength{\vscale}{0.505mm}}{} +\@ifclasswith{\@baseclass}{cookpaper}{\setlength{\hscale}{0.809mm}\setlength{\vscale}{0.740mm}}{} +\@ifclasswith{\@baseclass}{illustratedpaper}{\setlength{\hscale}{0.905mm}\setlength{\vscale}{0.909mm}}{} +\@ifclasswith{\@baseclass}{f24paper}{\setlength{\hscale}{0.762mm}\setlength{\vscale}{0.808mm}}{} +\@ifclasswith{\@baseclass}{a4paperlandscape}{\setlength{\hscale}{1.414mm}\setlength{\vscale}{0.707mm}}{} +\@ifclasswith{\@baseclass}{169paperlandscape}{\setlength{\hscale}{1.414mm}\setlength{\vscale}{0.562mm}}{} + +% Set the default page layout +\RequirePackage[ + paperwidth=210\hscale, + paperheight=297\vscale, +]{geometry} + +% Command to choose among the three possible layouts +\DeclareDocumentCommand{\pagelayout}{m}{% + \ifthenelse{\equal{margin}{#1}}{\marginlayout\marginfloatsetup}{}% + \ifthenelse{\equal{wide}{#1}}{\widelayout\widefloatsetup}{}% + \ifthenelse{\equal{fullwidth}{#1}}{\fullwidthlayout\widefloatsetup}{}% +} + +\newif\ifwidelayout% +\def\IfWideLayout{% + \ifwidelayout% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% +} + +% Layout #1: large margins +\newcommand{\marginlayout}{% + \newgeometry{ + top=27.4\vscale, + bottom=27.4\vscale, + inner=24.8\hscale, + textwidth=107\hscale, + marginparsep=6.2\hscale, + marginparwidth=47.7\hscale, + }% + \recalchead% + \widelayoutfalse% +} + +% Layout #2: small, symmetric margins +\newcommand{\widelayout}{% + \newgeometry{ + top=27.4\vscale, + bottom=27.4\vscale, + inner=24.8\hscale, + outer=24.8\hscale, + marginparsep=0mm, + marginparwidth=0mm, + }% + \recalchead% + \widelayouttrue% +} + +% Layout #3: no margins and no space above or below the body +\newcommand{\fullwidthpage}{% + \newgeometry{ + top=0mm, + bottom=0mm, + inner=0mm, + outer=0mm, + marginparwidth=0mm, + marginparsep=0mm, + }% + \recalchead% + \widelayouttrue% +} + +% Set the default page layout +\AtBeginDocument{\pagelayout{margin}} + +%---------------------------------------------------------------------------------------- +% HEADERS AND FOOTERS +%---------------------------------------------------------------------------------------- + +\RequirePackage{scrlayer-scrpage} % Customise head and foot regions + +% Set the header height to prevent a warning +%\setlength{\headheight}{27.4\vscale} +% Increase the space between header and text +\setlength{\headsep}{11\vscale} + +% Define some LaTeX lengths used in the page headers +\newlength{\headtextwidth} % This is the width of the text +\newlength{\headmarginparsep} % This is the width of the whitespace between text and margin +\newlength{\headmarginparwidth} % This is the width of the margin +\newlength{\headtotal} % This is the total width of the header +\newlength{\contentwidth} % An alias for \headtotal +\newcommand{\recalchead}{% Command to recalculate the header-related length when needed + \setlength{\headtextwidth}{\textwidth}% + \setlength{\headmarginparsep}{\marginparsep}% + \setlength{\headmarginparwidth}{\marginparwidth}% + \setlength{\headtotal}{\headtextwidth+\headmarginparsep+\headmarginparwidth}% + \setlength{\contentwidth}{\headtotal}% +} + +\AtBeginDocument{% Recalculate the header-related lengths + \recalchead% +} + +% Header style with chapter number, chapter title, and page in the header (used throughout the document) +\renewpagestyle{scrheadings}{% + {\smash{\hspace{-\headmarginparwidth}\hspace{-\headmarginparsep}\makebox[\headtotal][l]{% + \makebox[7\hscale][r]{\thepage}% + \makebox[3\hscale]{}\rule[-1mm]{0.5pt}{19\vscale-1mm}\makebox[3\hscale]{}% + \makebox[\headtextwidth][l]{\leftmark}}}}% + {\smash{\makebox[0pt][l]{\makebox[\headtotal][r]{% + \makebox[\headtextwidth][r]{\hfill\rightmark}% + \makebox[3\hscale]{}\rule[-1mm]{0.5pt}{19\vscale-1mm}\makebox[3\hscale]{}% + \makebox[7\hscale][l]{\thepage}}}}}% + {\smash{\makebox[0pt][l]{\makebox[\headtotal][r]{% + \makebox[\headtextwidth][r]{\hfill\rightmark}% + \makebox[3\hscale]{}\rule[-1mm]{0.5pt}{19\vscale-1mm}\makebox[3\hscale]{}% + \makebox[7\hscale][l]{\thepage}}}}}% +}{% + {}% + {}% + {}% +} + +% Header style with neither header nor footer (used for special pages) +\renewpagestyle{plain.scrheadings}{% + {}% + {}% + {}% +}{% + {}% + {}% + {}% +} + +% Header style with an empty header and the page number in the footer +\newpagestyle{pagenum.scrheadings}{% + {}% + {}% + {}% +}{% + {\makebox[\textwidth][r]{\thepage}}% + {\makebox[\textwidth][l]{\thepage}}% + {\makebox[\textwidth][l]{\thepage}}% +} + +% Header style with an empty header and the page number in the footer +\newpagestyle{centeredpagenum.scrheadings}{% + {}% + {}% + {}% +}{% + {\hspace{-\headmarginparwidth}\hspace{-\headmarginparsep}\makebox[\headtotal][l]{\hfill\thepage\hfill}} + {\makebox[0pt][l]{\makebox[\headtotal][r]{\hfill\thepage\hfill}}}% + {\makebox[0pt][l]{\makebox[\headtotal][r]{\hfill\thepage\hfill}}}% +} + +% Command to print a blank page +\newcommand\blankpage{% + \null% + \thispagestyle{empty}% + \newpage% +} + +% Set the default page style +\pagestyle{plain.scrheadings} + +%---------------------------------------------------------------------------------------- +% PARAGRAPH FORMATTING +%---------------------------------------------------------------------------------------- + +\RequirePackage{ragged2e} % Required to achieve better ragged paragraphs +\RequirePackage{setspace} % Required to easily set the space between lines +\RequirePackage{hyphenat} % Hyphenation for special fonts +\RequirePackage{microtype} % Improves character and word spacing +\RequirePackage{needspace} % Required to prevent page break right after a sectioning command +\RequirePackage{xspace} % Better print trailing whitespace + +% TODO: recognize space/indent justified/raggedright class options + +% Settings for a normal paragraph +\newcommand{\@body@par}{% + \justifying% Justify text + \singlespacing% Set the interline space to a single line + \frenchspacing% No additional space after periods + \normalfont% Use the default font + \normalsize% Use the default size +} + +% Settings for paragraphs in the margins +\newcommand{\@margin@par}{% + \justifying% justify text + \setlength{\RaggedRightParindent}{0em}% Suppress indentation + \setlength{\parindent}{0em}% Suppress indentation + \setlength{\parskip}{0.5pc}% Set the space between paragraphs + %\singlespacing% Set the space between lines + \frenchspacing% No additional space after periods + \normalfont% Use the default font + \footnotesize% Use a smaller size +} + +% By default, use @body@par settings +\@body@par + +%---------------------------------------------------------------------------------------- +% WIDE PARAGRAPHS +%---------------------------------------------------------------------------------------- + +% Environment for a wide paragraph +\NewDocumentEnvironment{widepar}{}{% + \if@twoside% + \Ifthispageodd{% + \begin{addmargin}[0cm]{-\marginparwidth-\marginparsep}% + }{% + \begin{addmargin}[-\marginparwidth-\marginparsep]{0cm}% + }% + \else% + \begin{addmargin}[0cm]{-\marginparwidth-\marginparsep}% + \fi% +}{% + \end{addmargin}% +} + +% Environment for a full width paragraph +\NewDocumentEnvironment{fullwidthpar}{}{% + \if@twoside% + \Ifthispageodd{% + \begin{addmargin}[-1in-\hoffset-\oddsidemargin]{-\paperwidth+1in+\hoffset+\oddsidemargin+\textwidth}% + }{% + \begin{addmargin}[-\paperwidth+1in+\hoffset+\oddsidemargin+\textwidth]{-\paperwidth+1in+\hoffset+\oddsidemargin+\marginparsep+\marginparwidth+\textwidth}% + }% + \else% + \begin{addmargin}[-1in-\hoffset-\oddsidemargin]{-\paperwidth+1in+\hoffset+\oddsidemargin+\textwidth}% + \fi% +}{% + \end{addmargin}% +} + +% Environment for a wide equation +\NewDocumentEnvironment{wideequation}{}{% + \begin{widepar}% + \begin{equation}% +}{% + \end{equation}% + \end{widepar}% +} + +%---------------------------------------------------------------------------------------- +% FOOTNOTES, MARGINNOTES AND SIDENOTES +%---------------------------------------------------------------------------------------- + +\RequirePackage[section]{placeins} % Prevent floats to cross sections +\extrafloats{100} % Require more floats + +\RequirePackage{marginnote} % Provides options for margin notes +%\RequirePackage{marginfix} % Make marginpars float freely; it should not be loaded as it prevents the marginnotes to stay aligned with the main text +\RequirePackage{sidenotes} % Use sidenotes +\RequirePackage{chngcntr} % Reset counters at sections + +% TODO: see also page 440 of the KOMA-script guide +\RequirePackage[ + bottom, + symbol*, + hang, + flushmargin, + % perpage, + stable, +]{footmisc} % Required to set up the footnotes +\RequirePackage{footnotebackref} % Creates back references from footnotes to text + +% Fix the color of the footnote marker when back-referenced +\patchcmd{\footref}{\ref}{\hypersetup{colorlinks=black}\ref}{}{}% +% Workaround to fix back references +\edef\BackrefFootnoteTag{bhfn:\theBackrefHyperFootnoteCounter}% + +% FIXME: I am not able to choose the paragraph layout of footnotes, probably the footnotes package conflicts with scrbook. +%\renewcommand{\footnotelayout}{\@margin@par} + +%---------------------------------------------------------------------------------------- + +% Justify and format margin notes +\renewcommand*{\raggedleftmarginnote}{} % Suppress left margin +\renewcommand*{\raggedrightmarginnote}{} % Suppress right margin +\renewcommand*{\marginfont}{\@margin@par} % Format marginnotes according to \@marginpar (see above) +\renewcommand{\marginnotevadjust}{0.8\vscale} % Bring all marginnotes downwards a bit +%\marginposadjustment=1\vscale % Bring downwards also the marginpars +%\marginheightadjustment=10cm % Adjust the height of the margins for each page +%\RequirePackage[marginnote=true]{snotez} % Provides options for sidenotes + +% Copied from snotez's \sidenote +\def\kao@if@nblskip#1{% + \expandafter\ifx\@car#1\@nil*% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% +} + +% Command to detect whether we are inside a tcolorbox environment +\newif\ifinfloat % First, set this flag whenever we are in a tcolorbox environment... +\AtBeginEnvironment{tcolorbox}{\infloattrue\renewcommand{\marginnotevadjust}{-1.4\vscale}} +\AtBeginEnvironment{minipage}{\infloattrue} + +\def\IfInFloatingEnvir{% ...Then, detect the flag + \ifinfloat% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% +} + + +% Redefine the command to print marginnotes: +% (a) the optional offset argument goes at the first position +% (b) the offset can also be a multiple of baselineskip, like for snotez's \sidenote +% Usage: \marginnote[]{Text of the note.} +\let\oldmarginnote\marginnote% +\RenewDocumentCommand\marginnote{ o m }{% + \IfNoValueOrEmptyTF{#1}{% + \IfInFloatingEnvir{% + \oldmarginnote{#2}% + }{% + \marginpar{\@margin@par#2}% + }% + }{% + \oldmarginnote{#2}[\kao@if@nblskip{#1}{\@cdr#1\@nil\baselineskip}{#1}]% + }% +} + +% Initially set the sidenote counter to zero instead of 1, and update it before printing the sidenote. +\setcounter{sidenote}{0}% +\RenewDocumentCommand\sidenote{ o o +m }{% + \IfNoValueOrEmptyTF{#1}{% + \refstepcounter{sidenote}% This command has been moved here + }{% + }% + \sidenotemark[#1]% + \sidenotetext[#1][#2]{#3}% + \@sidenotes@multimarker% +} + +% Formatting sidenote markers +\RenewDocumentCommand\@sidenotes@thesidenotemark{ m }{% Format the marker + \leavevmode% + \ifhmode% + \edef\@x@sf{\the\spacefactor}% + \nobreak% + \fi% + \hbox{\@textsuperscript{\normalfont#1}}% + \ifhmode% + \spacefactor\@x@sf% + \fi% + \relax% +}% + +% Formatting the sidenote text +\RenewDocumentCommand\sidenotetext{ o o +m }{% number, offset, text + \IfNoValueOrEmptyTF{#1}{% + \marginnote[#2]{\thesidenote:\enskip#3}% + }{% + \marginnote[#2]{#1:\enskip#3}% + }% +} + +%---------------------------------------------------------------------------------------- +% FIGURES, TABLES, LISTINGS AND CAPTIONS +%---------------------------------------------------------------------------------------- + +\RequirePackage{graphicx} % Include figures +\setkeys{Gin}{width=\linewidth,totalheight=\textheight,keepaspectratio} % Improves figure scaling +\RequirePackage{tikz} % Allows to draw custom shapes +\RequirePackage{tikzpagenodes} % Allows to anchor tikz nodes to page elements +\RequirePackage{booktabs} % Nicer tables +\RequirePackage{multirow} % Cells occupying multiple rows in tables +\RequirePackage{multicol} % Multiple columns in dictionary +\RequirePackage{rotating} % Allows tables and figures to be rotated +\RequirePackage{listings} % Print code listings +%\RequirePackage{minted} +\RequirePackage[hypcap=true]{caption} % Correctly placed anchors for hyperlinks +% \RequirePackage{atbegshi} +% \RequirePackage{perpage} +\let\c@abspage\relax +% \newcommand{\pp@g@sidenote}{} +\RequirePackage{floatrow} % Set up captions of floats +%\RequirePackage{dblfloatfix} % Better positioning of wide figures and tables + +% Improve the figure placing (see https://www.overleaf.com/learn/latex/Tips) +\def\topfraction{.9}% +\def\textfraction{0.35}% +\def\floatpagefraction{0.8}% + +% Set the space between floats and main text +\renewcommand\FBaskip{.4\topskip}% +\renewcommand\FBbskip{\FBaskip}% + +% Tighten up space between displays (e.g., equations) and make symmetric (from tufte-latex) +\setlength\abovedisplayskip{6pt plus 2pt minus 4pt}% +\setlength\belowdisplayskip{6pt plus 2pt minus 4pt}% +\abovedisplayskip 10\p@ \@plus2\p@ \@minus5\p@% +\abovedisplayshortskip \z@ \@plus3\p@% +\belowdisplayskip \abovedisplayskip% +\belowdisplayshortskip 6\p@ \@plus3\p@ \@minus3\p@% + +\setlength\columnseprule{.4pt} % Set the width of vertical rules in tables + +% The marginfix package prevents the margin notes to stay aligned with the main text, so it cannot be used. However, we define the \marginskip command, which is the only command we need from that package. +\newcommand\marginskip[1]{% + \marginpar{\@margin@par\vspace{#1 - \baselineskip}}% We subtract the \baselineskip that we have in margin pars. +} + +\newlength{\kaomarginskipabove} % Specify the space above a marginfigure, margintable or marginlisting +\newlength{\kaomarginskipbelow} % Specify the space below a marginfigure, margintable or marginlisting +\setlength{\kaomarginskipabove}{3mm plus 2pt minus 2pt} +\setlength{\kaomarginskipbelow}{3mm plus 2pt minus 2pt} + +% Environment to hold a margin figure (from the sidenotes package) +% We redefine it here because we want to use our own caption formatting. +\RenewDocumentEnvironment{marginfigure}{o}{% + \FloatBarrier% + \marginskip{\kaomarginskipabove}% + \begin{lrbox}{\@sidenotes@marginfigurebox}% + \begin{minipage}{\marginparwidth}% + \captionsetup{type=figure}% +}{% + \end{minipage}% + \end{lrbox}% + \marginnote[#1]{\usebox{\@sidenotes@marginfigurebox}}% + \marginskip{\kaomarginskipbelow}% +} + +% Environment to hold a margin table (from the sidenotes package) +\RenewDocumentEnvironment{margintable}{o}{% + \FloatBarrier% + \marginskip{\kaomarginskipabove}% + \begin{lrbox}{\@sidenotes@margintablebox}% + \begin{minipage}{\marginparwidth}% + \captionsetup{type=table}% +}{% + \end{minipage}% + \end{lrbox}% + \marginnote[#1]{\usebox{\@sidenotes@margintablebox}}% + \marginskip{\kaomarginskipbelow}% +} + +% Environment to hold a margin listing +\newsavebox{\@sidenotes@marginlistingbox}% +\NewDocumentEnvironment{marginlisting}{o}{% The optional parameter is the vertical offset + \FloatBarrier% + \marginskip{\kaomarginskipabove}% + \begin{lrbox}{\@sidenotes@marginlistingbox}% + \begin{minipage}{\marginparwidth}% + \captionsetup{type=lstlisting}% +}{% + \end{minipage}% + \end{lrbox}% + \marginnote[#1]{\usebox{\@sidenotes@marginlistingbox}}% + \marginskip{\kaomarginskipbelow}% +} + +% Change the position of the captions +\DeclareFloatSeparators{marginparsep}{\hskip\marginparsep}% + +% Detect whether there is a caption in the current environment by switching the kaocaption toggle when \caption is called. If there is no caption, reset the floatsetup. Without this fix, the floatrow package will align the environment to the main text if there is a caption, but to the margin if there is no caption. +\newtoggle{kaocaption} +\AtBeginEnvironment{figure}{% + \let\oldcaption\caption% + \RenewDocumentCommand{\caption}{s o m}{% + \IfBooleanTF{#1}{% + \oldcaption*{#3}% + }{% + \IfValueTF{#2}{% + \oldcaption[#2]{#3}% + }{% + \oldcaption{#3}% + }% + }% + \toggletrue{kaocaption}% + }% +} +\AtEndEnvironment{figure}{% + \iftoggle{kaocaption}{% + }{% + \RawFloats% + \centering% + }% + \togglefalse{kaocaption}% +} +\AtBeginEnvironment{table}{% + \let\oldcaption\caption% + \RenewDocumentCommand{\caption}{s o m}{% + \IfBooleanTF{#1}{% + \oldcaption*{#3}% + }{% + \IfValueTF{#2}{% + \oldcaption[#2]{#3}% + }{% + \oldcaption{#3}% + }% + }% + \toggletrue{kaocaption}% + }% +} +\AtEndEnvironment{table}{% + \iftoggle{kaocaption}{% + }{% + \RawFloats% + \centering% + }% + \togglefalse{kaocaption}% +} + +% Change the formatting of the captions +\addtokomafont{captionlabel}{\bfseries} % Bold font for the figure label +% Declare a new style to format the caption according to \@margin@par (see above) +\DeclareCaptionFormat{margin}{\@margin@par #1#2#3} +% Declare a new caption style for lstlistings +\newsavebox\mycap +\DeclareCaptionFormat{llap}{% + \begin{lrbox}{\mycap}% + \begin{minipage}{\marginparwidth}% + \@margin@par #1:#2#3% + \end{minipage}% + \end{lrbox}% + \marginnote[0.2cm]{\usebox\mycap}% +} +% Set the global caption style +\captionsetup{ + format=margin, % Use the style previously declared + strut=no,% + %hypcap=true, % Links point to the top of the figure + singlelinecheck=false,% + %width=\marginparwidth, + indention=0pt, % Suppress indentation + parindent=0pt, % Suppress space between paragraphs + aboveskip=6pt, % Increase the space between the figure and the caption + belowskip=6pt, % Increase the space between the caption and the table +} + +% Needed to have continued figures and tables (https://en.wikibooks.org/wiki/LaTeX/Floats,_Figures_and_Captions#Figures_in_multiple_parts) +\DeclareCaptionLabelFormat{cont}{#1~#2\alph{ContinuedFloat}} +\captionsetup[ContinuedFloat]{labelformat=cont} + +% Captions for the 'margin' layout +\NewDocumentCommand{\marginfloatsetup}{}{% +\if@twoside% + \floatsetup[figure]{% Captions for figures + margins=hangoutside,% Put captions in the margins + facing=yes,% + capposition=beside,% + capbesideposition={bottom,outside},% + capbesideframe=yes,% + capbesidewidth=\marginparwidth,% Width of the caption equal to the width of the margin + capbesidesep=marginparsep,% + floatwidth=\textwidth,% Width of the figure equal to the width of the text + }% + \floatsetup[widefigure]{% Captions for wide figures + margins=hangoutside,% Put captions below the figure + facing=yes,% + capposition=bottom% + }% + \floatsetup[table]{% Captions for tables + margins=hangoutside,% Put captions in the margin + facing=yes,% + capposition=beside,% + capbesideposition={top,outside},% + %capbesideposition=outside, + capbesideframe=yes,% + capbesidewidth=\marginparwidth,% Width of the caption equal to the width of the margin + capbesidesep=marginparsep,% + floatwidth=\textwidth,% Width of the figure equal to the width of the text + }% + \floatsetup[widetable]{% Captions for wide tables + margins=hangoutside,% Put captions above the table + facing=yes,% + capposition=above% + }% + \floatsetup[longtable]{% Captions for longtables + margins=raggedright,% Overwrite the hangright setting from the `table' environment + %LTcapwidth=table,% Set the width of the caption equal to the table's + }% + \floatsetup[lstlisting]{% Captions for lstlistings + margins=hangoutside,% Put captions in the margin + facing=yes,% + capposition=beside,% + capbesideposition={top,outside},% + %capbesideposition=outside, + capbesideframe=yes,% + capbesidewidth=\marginparwidth,% Width of the caption equal to the width of the margin + capbesidesep=marginparsep,% + floatwidth=\textwidth,% Width of the figure equal to the width of the text + }% + \floatsetup[listing]{% Captions for listings (minted package) + margins=hangoutside,% Put captions in the margin + facing=yes,% + capposition=beside,% + capbesideposition={top,outside},% + %capbesideposition=outside, + capbesideframe=yes,% + capbesidewidth=\marginparwidth,% Width of the caption equal to the width of the margin + capbesidesep=marginparsep,% + floatwidth=\textwidth,%Width of the figure equal to the width of the text + }% + \captionsetup*[lstlisting]{% + format=llap,% + labelsep=space,% + singlelinecheck=no,% + belowskip=-0.6cm,% + }% +\else% + \floatsetup[figure]{% Captions for figures + margins=hangright,% Put captions in the margins + facing=yes,% + capposition=beside,% + capbesideposition={bottom,right},% + capbesideframe=yes,% + capbesidewidth=\marginparwidth,% Width of the caption equal to the width of the margin + capbesidesep=marginparsep,% + floatwidth=\textwidth,% Width of the figure equal to the width of the text + }% + \floatsetup[widefigure]{% Captions for wide figures + margins=hangright,% Put captions below the figure + facing=no,% + capposition=bottom% + }% + \floatsetup[table]{% Captions for tables + margins=hangright,% Put captions in the margin + facing=yes,% + capposition=beside,% + capbesideposition={top,right},% + %capbesideposition=outside, + capbesideframe=yes,% + capbesidewidth=\marginparwidth,% Width of the caption equal to the width of the margin + capbesidesep=marginparsep,% + floatwidth=\textwidth,% Width of the figure equal to the width of the text + }% + \floatsetup[widetable]{% Captions for wide tables + margins=hangright,% Put captions above the table + facing=no,% + capposition=above% + }% + \floatsetup[longtable]{% Captions for longtables + margins=raggedright,% Overwrite the hangright setting from the `table' environment + %LTcapwidth=table,% Set the width of the caption equal to the table's + }% + \floatsetup[lstlisting]{% Captions for lstlisting + margins=hangright,% Put captions in the margin + facing=yes,% + capposition=beside,% + capbesideposition={top,right},% + %capbesideposition=outside, + capbesideframe=yes,% + capbesidewidth=\marginparwidth,% Width of the caption equal to the width of the margin + capbesidesep=marginparsep,% + floatwidth=\textwidth,% Width of the figure equal to the width of the text + }% + \floatsetup[listing]{% Captions for listing (minted package) + margins=hangright,% Put captions in the margin + facing=yes,% + capposition=beside,% + capbesideposition={top,right},% + %capbesideposition=outside, + capbesideframe=yes,% + capbesidewidth=\marginparwidth,% Width of the caption equal to the width of the margin + capbesidesep=marginparsep,% + floatwidth=\textwidth,% Width of the figure equal to the width of the text + }% + \captionsetup*[lstlisting]{% + format=llap,% + labelsep=space,% + singlelinecheck=no,% + belowskip=-0.6cm,% + }% +\fi% +} + +% Captions for the 'wide' layout +\NewDocumentCommand{\widefloatsetup}{}{% + \floatsetup[figure]{ % Captions for figures + capposition=bottom,% + margins=centering,% + floatwidth=\textwidth% + } + \floatsetup[widefigure]{ % Captions for wide figures + margins=hangoutside, % Put captions below the figure + facing=yes,% + capposition=bottom% + } + \floatsetup[table]{ % Captions for tables + capposition=above,% + margins=centering,% + floatwidth=\textwidth% + } + \floatsetup[widetable]{ % Captions for wide tables + margins=hangoutside, % Put captions above the table + facing=yes,% + capposition=above% + } + \floatsetup[lstlisting]{ % Captions for lstlistings + capposition=above,% + margins=centering,% + floatwidth=\textwidth% + } + \floatsetup[listing]{ % Captions for listings (minted package) + capposition=above,% + margins=centering,% + floatwidth=\textwidth% + } + \captionsetup*[lstlisting]{% Captions style for lstlistings + %format=margin,% + labelsep=colon,% + strut=no,% + singlelinecheck=false,% + indention=0pt,% + parindent=0pt,% + aboveskip=6pt,% + belowskip=6pt,% + belowskip=-0.1cm% + } +} + +%---------------------------------------------------------------------------------------- +% TOC, LOF & LOT +%---------------------------------------------------------------------------------------- + +\RequirePackage{tocbasic} % Required to customise the TOC + +% Show an entry for the TOC in the TOC +\setuptoc{toc}{totoc} + +% Choose the levels in table of contents +\setcounter{tocdepth}{\subsectiontocdepth} + +% Customise the list of listings +\renewcommand{\lstlistlistingname}{List of Listings}% Change the title +\newcommand{\lstlistingtocdepth}{\sectiontocdepth}% Set the depth +\newcommand{\listoflistings}{\lstlistoflistings}% Provide the alias \listoflistings +\newcommand{\listoflstlistings}{\lstlistoflistings}% Provide the alias \listoflstlistings + +% Define the style for toc entries +\@ifpackagelater{scrbase}{2019/10/11}{% + \DeclareTOCStyleEntries[indent=0em,numwidth=2em,dynnumwidth=yes,pagenumberwidth=2.1em]{tocline}{figure,table,lstlisting}% + \DeclareTOCStyleEntries[dynnumwidth=yes]{tocline}{subsubsection,subsection,section,chapter,part}% + \DeclareTOCStyleEntries[pagenumberwidth=2.5em]{tocline}{chapter,part}% + \DeclareTOCStyleEntries[pagenumberwidth=2.1em]{tocline}{subsubsection,subsection,section}% +}{% + \DeclareTOCStyleEntries[indent=0em,numwidth=2em,dynnumwidth=yes]{tocline}{figure,table,lstlisting}% + \DeclareTOCStyleEntries[dynnumwidth=yes]{tocline}{subsubsection,subsection,section,chapter,part}% +} + +% Define the names for the headings +% \renewcaptionname{english}{\contentsname}{Detailed Contents} +% \renewcaptionname{english}{\listfigurename}{Figures} +% \renewcaptionname{english}{\listtablename}{Tables} +% \newcaptionname{english}{\listtheoremname}{Theorems} + +%---------------------------------------------------------------------------------------- +% MARGIN TOC +%---------------------------------------------------------------------------------------- + +\RequirePackage{etoc} % Required to insert local tables of contents + +\newcounter{margintocdepth} % Set the depth of the margintoc +\setcounter{margintocdepth}{\subsectiontocdepth} % By default to subsections + +\newlength{\mtocshift} % Length of the vertical offset used for margin tocs +\setlength{\mtocshift}{1\vscale}% \mtocshift is overridden by \setchapterstyle + +% Optional title for margintoc (by hCarlFelix, +% https://github.com/fmarotta/kaobook/issues/101) +% We want to create an additional entries in the toc which is to be used for the margintoc +% We define these as mtocsection and mtocsubsection for section and subsection` +\newcommand{\mtocsection}[1]{ + \etoctoccontentsline{mtocsection}{% + \ifnum\value{secnumdepth}>0 \protect\numberline{\thesection}% + \else \protect\nonumberline% + \fi #1}% +} +\newcommand{\mtocsubsection}[1]{ + \etoctoccontentsline{mtocsubsection}{% + \ifnum\value{secnumdepth}>1 \protect\numberline{\thesubsection}% + \else \protect\nonumberline% + \fi #1}% +} + +% Next, we redefine \section and \subsection so that they accept an additional parameter +% \section[alternative-title-for-toc]{title-as-written-in-text}[alternative-title-for-margintoc] + +% Adapted from Frank Mittelbach's answer at Stackexchange +% https://tex.stackexchange.com/a/109560/226693 +\let\oldsection\section % save the old command +\let\oldsubsection\subsection % save the old command + +\RenewDocumentCommand\section{s o m o}{% + \IfBooleanTF{#1}{% + \oldsection*{#3} + \IfNoValueF{#2}{% if TOC arg is given create a TOC entry + \addxcontentsline{toc}{section}[\thesection]{#2}% + }% + }{% no star given + \IfNoValueTF{#2}{% + \oldsection{#3}% + }{% no TOC arg + \oldsection[#2]{#3}% + }% + \IfNoValueTF{#4}{% optional label given, if not we do nothing + % \mtocsection{#3}% + \IfNoValueTF{#2}{% + \mtocsection{#3}% when no optional toc title, use main title + }{% no TOC arg + \mtocsection{#2}% when toc optional title is given, use it + }% + }{% + \mtocsection{#4}% + }% + }% +} + +\RenewDocumentCommand\subsection{s o m o}{% + \IfBooleanTF{#1}{% + \oldsubsection*{#3}% + \IfNoValueF{#2}{% if TOC arg is given create a TOC entry + \addxcontentsline{toc}{subsection}[\thesubsection]{#2}% + }% + }{% no star given + \IfNoValueTF{#2}{% + \oldsubsection{#3}% + }{% no TOC arg + \oldsubsection[#2]{#3}% + }% + \IfNoValueTF{#4}{% optional label given, if not we do nothing + \IfNoValueTF{#2}{% + \mtocsubsection{#3}% when no optional toc title, use main title + }{% no TOC arg + \mtocsubsection{#2}% when toc optional title is given, use it + }% + }{% + \mtocsubsection{#4}% + }% + }% +} + +\etocsetlevel{mtocsection}{6}% dummy sectioning level +\etocsetlevel{mtocsubsection}{6}% dummy sectioning level + +% Command to print a table of contents in the margin +\NewDocumentCommand{\margintoc}{O{\mtocshift}}{ % The first parameter is the vertical offset; by default it is \mtocshift + \begingroup% + % Move regular section and subsection to level 6 so that they won't be included and instead set let the mtoc versions take their place. + % Adapted from https://tex.stackexchange.com/a/133559/226693 + \etocsetlevel{section}{6} + \etocsetlevel{subsection}{6} + \etocsetlevel{mtocsection}{1} + \etocsetlevel{mtocsubsection}{2} + + % Define default widths + \def\margintocnumwidth{-.8mm}% + \def\margintocpagenumwidth{8pt}% + \setlength{\RaggedRightParfillskip}{0pt} + + % Dry run to get the needed widths + \etocsetstyle{mtocsection}% + {}% + {\setbox0\hbox{{\usekomafont{section}\small\etocthenumber\kern.8mm}}%% + \setbox1\hbox{{\usekomafont{section}\small\etocthepage}}}% + {\ifdim\wd0>\margintocnumwidth \edef\margintocnumwidth{\the\wd0} \fi%% + \ifdim\wd1>\margintocpagenumwidth \edef\margintocpagenumwidth{\the\wd1} \fi}% + {}% + \etocsetstyle{mtocsubsection}% + {}% + {\setbox0\hbox{{\usekomafont{section}\small\mdseries\etocthenumber\kern.8mm}}% + \setbox1\hbox{{\usekomafont{section}\small\mdseries\etocthepage}}}% + {\ifdim\wd0>\margintocnumwidth \edef\margintocnumwidth{\the\wd0} \fi% + \ifdim\wd1>\margintocpagenumwidth \edef\margintocpagenumwidth{\the\wd1} \fi}% + {}% + \etocsetstyle{subsubsection}% + {}% + {}% + {}% + {}% + \etocsetstyle{paragraph}% + {}% + {}% + {}% + {}% + \etocsettocstyle{}{% + \global\let\margintocnumwidth\margintocnumwidth% + \global\let\margintocpagenumwidth\margintocpagenumwidth% + }% + \localtableofcontents% + + % Set the style for section entries + \etocsetstyle{mtocsection}% + {\parindent 0pt \parskip 2.5pt \parfillskip 0pt \RaggedRight}% + {\leftskip \margintocnumwidth \rightskip \margintocpagenumwidth}% + {\makebox[0pt][r]{\makebox[\margintocnumwidth][l]{\etocnumber}}\etocname\nobreak\leaders\hbox{\hbox to 1.5ex {\hss.\hss}}\hfill\rlap{\makebox[\margintocpagenumwidth][r]{\etocpage}}\par}% + {}% + % Set the style for subsection entries + \etocsetstyle{mtocsubsection}% + {\parindent 0pt \parskip 0pt \parfillskip 0pt \RaggedRight}% + {\leftskip \margintocnumwidth \rightskip \margintocpagenumwidth}% + {\makebox[0pt][r]{\makebox[\margintocnumwidth][l]{\mdseries\etocnumber}}{\mdseries\etocname\nobreak\leaders\hbox{\hbox to 1.5ex {\hss.\hss}}\hfill\rlap{\makebox[\margintocpagenumwidth][r]{\mdseries\etocpage}}}\par}% + {\parskip 2.5pt}% + % Set the global style of the toc + \etocsettocstyle{\usekomafont{section}\small}{}% + \etocsetnexttocdepth{\themargintocdepth}% + % Print the table of contents in the margin + \marginnote[#1]{\localtableofcontents}% + \FloatBarrier% + \endgroup% +} + +%---------------------------------------------------------------------------------------- +% ENCODING AND FONTS +%---------------------------------------------------------------------------------------- + +\newcommand{\kao@fontmethodModern}{% + \RequirePackage{amssymb} % Must be loaded before unicode-math + \RequirePackage[force]{filehook} % Fixes an error + \RequirePackage{unicode-math} % Math fonts in xetexorluatex + \setromanfont[ % Libertinus Serif font + Scale=1.04 + ]{Libertinus Serif} + \setsansfont[ % Libertinus Sans font + Scale=1 + ]{Libertinus Sans} + \setmonofont[ % Libertinus Mono font + Scale=.89 + ]{Liberation Mono} + \setmathfont{Libertinus Math} % Libertinus Math font + \ifluatex + \else + \RequirePackage{morewrites} % Fix some errors related to floats (not necessary with LuaLaTeX + \fi% +} +\newcommand{\kao@fontmethodTex}{% + \RequirePackage[utf8]{inputenc} % utf8 encoding in the input (.tex) file + \RequirePackage[T1]{fontenc} % utf8 encoding in the output (.pdf) file + + \RequirePackage{amssymb} % Math symbols, including \blacktriangleright, used for bullets + \RequirePackage[scaled=.97,helvratio=.93,p,theoremfont]{newpxtext} % Serif palatino font + \RequirePackage[vvarbb,smallerops,bigdelims]{newpxmath} % Math palatino font + \RequirePackage[scaled=.85]{beramono} % Monospace font + \RequirePackage[scr=rsfso,cal=boondoxo]{mathalfa} % Mathcal from STIX, unslanted a bit + \RequirePackage{morewrites} % Fix some errors related to floats +} + +\ifthenelse% + {\equal{modern}{\kao@fontmethod}}{\kao@fontmethodModern}% +{\ifthenelse% + {\equal{tex}{\kao@fontmethod}}{\kao@fontmethodTex}% +{ + \PackageError{kao}{% + Invalid fontmethod choice \kao@fontmethod.% + }{% + Should be one of "modern" or "tex"% + } +}} + +% When using the Palatino (newpxtext) font, it is better to use a +% slightly larger stretch. +%\setstretch{1.10} +\linespread{1.07} % Give Palatino more leading (space between lines) + +% Fix for the subequation environment (https://tex.stackexchange.com/questions/27053/too-much-space-between-full-paragraph-and-subequations-env) +\preto\subequations{\ifhmode\unskip\fi} + +%---------------------------------------------------------------------------------------- +% HYPERREFERENCES +%---------------------------------------------------------------------------------------- + +\RequirePackage{hyperref} % Required for hyperlinks +\RequirePackage{bookmark} % Required for pdf bookmarks + +\PassOptionsToPackage{hyphens}{url} % Break long URLs and use hyphens to separate the pieces + +% Color settings should be done in the next \hypersetup +\hypersetup{ % Set up hyperref options + unicode, % Use unicode for links + pdfborder={0 0 0}, % Suppress border around pdf + %xetex, + %pagebackref=true, + %hyperfootnotes=false, % We already use footmisc + bookmarksdepth=section, + bookmarksopen=true, % Expand the bookmarks as soon as the pdf file is opened + %bookmarksopenlevel=4, + linktoc=all, % Toc entries and numbers links to pages + breaklinks=true, + colorlinks=true, +} + +% Define a new color for the footnote marks +\def\@footnotecolor{black} +\define@key{Hyp}{footnotecolor}{% + \HyColor@HyperrefColor{#1}\@footnotecolor% +} +\def\@footnotemark{% + \leavevmode + \ifhmode\edef\@x@sf{\the\spacefactor}\nobreak\fi + \stepcounter{Hfootnote}% + \global\let\Hy@saved@currentHref\@currentHref + \hyper@makecurrent{Hfootnote}% + \global\let\Hy@footnote@currentHref\@currentHref + \global\let\@currentHref\Hy@saved@currentHref + \hyper@linkstart{footnote}{\Hy@footnote@currentHref}% + \@makefnmark + \hyper@linkend + \ifhmode\spacefactor\@x@sf\fi + \relax +} + +% Redefine the \thanks command to allow users to use \label within \thanks without getting warnings +\let\oldthanks\thanks +\renewcommand\thanks[1]{% + \label{bhfn:0}% + \oldthanks{#1}% +} + +% Adjust the colour of the footnotes marks using the colour defined above +\renewcommand\@makefntext[1]{% + \renewcommand\@makefnmark{% + \mbox{\textsuperscript{\normalfont% + \hyperref[\BackrefFootnoteTag]{% + \color{\@footnotecolor}{\@thefnmark}% + }}\,% + }% + }% + \BHFN@OldMakefntext{#1}% +} + +%---------------------------------------------------------------------------------------- +% COLOURS +%---------------------------------------------------------------------------------------- + +% Uncomment to have coloured headings +%\addtokomafont{title}{\color{Maroon}} +%\addtokomafont{part}{\color{Maroon}} +%\addtokomafont{chapter}{\color{Maroon}} +%\addtokomafont{section}{\color{Maroon}} +%\addtokomafont{subsection}{\color{Maroon}} +%\addtokomafont{subsubsection}{\color{Maroon}} +%\addtokomafont{paragraph}{\color{Maroon}} +%\addtokomafont{captionlabel}{\color{Blue}} +%\addtokomafont{pagenumber}{\color{Maroon}} + +% Choose the default colors +\hypersetup{ + %allcolors=DarkGreen, + %anchorcolor=Red, + %citecolor=DarkOrange!70!black, + citecolor=OliveGreen, + filecolor=OliveGreen, + %linkcolor=Blue, + linkcolor=Black, + %pagecolor = Blue, + %menucolor=Red, + %runcolor=Red, + urlcolor=OliveGreen, +} + +%---------------------------------------------------------------------------------------- +% ITEMS +%---------------------------------------------------------------------------------------- + +\renewcommand{\labelitemi}{\small$\blacktriangleright$} % Use a black triangle for the first level of \item's +\renewcommand{\labelitemii}{\textbullet} % Use a bullet for the second level of \item's +\RequirePackage[inline]{enumitem} % Used to customise lists (in particular, we don't want to put whitespace between items) +\setlist[itemize]{noitemsep} +\setlist[enumerate]{noitemsep} +\setlist[description]{noitemsep} + +%---------------------------------------------------------------------------------------- +% SIMPLE BOXED ENVIRONMENT +%---------------------------------------------------------------------------------------- + +% kaobox +\RequirePackage[most]{tcolorbox} + +% Define a new environment using the style created above +\newtcolorbox{kaobox}[1][]{ + breakable, + before skip=1.5\topskip, + after skip=1.5\topskip, + left skip=0pt, + right skip=0pt, + left=4pt, + right=4pt, + top=2pt, + bottom=2pt, + lefttitle=4pt, + righttitle=4pt, + toptitle=2pt, + bottomtitle=2pt, + sharp corners, + boxrule=0pt, + titlerule=.4pt, + colback=RoyalBlue!25!White, + colbacktitle=RoyalBlue!25!White, + coltitle=black, + colframe=black, + fonttitle=\bfseries, + #1 +} + +%---------------------------------------------------------------------------------------- +% ENVIRONMENT WITH A COUNTER +%---------------------------------------------------------------------------------------- + +% Define an environment titled 'Comment' and numbered incrementally +\newenvironment{kaocounter}{ + \refstepcounter{kaocounter} + \begin{kaobox}[title=Comment~\thekaocounter\autodot] +}{ + \end{kaobox} +} + +% Define the commands to manage the counter for the 'kaocounter' environment +\newcounter{kaocounter} +\counterwithin{kaocounter}{section} +\newcommand*{\kaocounterformat}{% Format for the caption + Comment~\thekaocounter\csname autodot\endcsname} +\newcommand*{\fnum@kaocounter}{\kaocounterformat} + + +%---------------------------------------------------------------------------------------- +% FLOATING ENVIRONMENT WITH TOC ENTRIES +%---------------------------------------------------------------------------------------- + +% Define a floating environment +\newenvironment{kaofloating}{% + \@float{kaofloating}% +}{% + \end@float% +} + +% Configure the 'kaofloating' environment +\newcommand*{\fps@floatingbox}{tbph}% Allowed positions for the environment (top, bottom, own page, here) +\newcommand*{\ftype@floatingbox}{5}% Set the type of float (floats of the same type cannot change their order; figures and tables are type 1 and 2 respectively) +\newcommand*{\floatingboxformat}{% Set a title of the environment + Insight~\thefloatingbox\csname autodot\endcsname} +\newcommand*{\fnum@floatingbox}{\floatingboxformat}% Use the environment title +\newcommand*{\ext@floatingbox}{loi}% Choose the extension of the auxiliary file for this environment + +\addtotoclist[float]{loi}% Keep track of 'kaofloating' environments for a "List of Insights" +\newcommand*{\listofloiname}{List of Insights}% Choose the title for the "List of Insights" +\newcommand*{\l@floatingbox}{\l@figure}% Format the LOI +\newcommand*{\listofinsights}{\listoftoc{loi}}% User-friendly command to print the LOI + +%---------------------------------------------------------------------------------------- +% ADDITIONAL PACKAGES +%---------------------------------------------------------------------------------------- + +% Productivity +\RequirePackage{pdfpages} % Insert PDF pages +\RequirePackage{subfiles} % Adopt a modular structure +\RequirePackage{todonotes} % Add useful notes in the margins + +% Listings code +\RequirePackage{listings} % Code +%\RequirePackage{minted} (must be loaded before scrhack) + +% Configure the listings +\definecolor{listingkeywords}{rgb}{0.0, 0.5, 0.0} +\definecolor{listingidentifiers}{rgb}{0, 0, 0} +\definecolor{listingcomments}{rgb}{0.25, 0.5, 0.5} +\definecolor{listingstrings}{rgb}{0.73, 0.13, 0.13} +\definecolor{listingnumbers}{rgb}{0.25, 0.25, 0.25} +% Define a fancy style +\lstdefinestyle{kaolst}{ + aboveskip=0.7\topskip, + belowskip=0.1\topskip, + basicstyle=\small\ttfamily, + commentstyle=\color{listingcomments}\itshape, + keywordstyle=\color{listingkeywords}\bfseries, + numberstyle=\scriptsize\color{listingnumbers}\ttfamily, + stringstyle=\color{listingstrings}, + identifierstyle=\color{listingidentifiers}, + backgroundcolor=\color{White}, + breakatwhitespace=false, + breaklines=true, + captionpos=t, + keepspaces=true, + showspaces=false, + showstringspaces=false, + showtabs=false, + numbers=left, + numbersep=1em, + %frame=lines, + frame=l, + framerule=.7pt, + tabsize=4, + defaultdialect=[LaTeX]Tex, +} +% Define a plain style as well +\lstdefinestyle{kaolstplain}{ + aboveskip=0.6\topskip, + belowskip=-0.1\topskip, + basicstyle=\small\ttfamily, + commentstyle=\color{listingcomments}\itshape, + keywordstyle=\color{listingkeywords}\bfseries, + numberstyle=\scriptsize\color{listingnumbers}\ttfamily, + stringstyle=\color{listingstrings}, + identifierstyle=\color{listingidentifiers}, + backgroundcolor=\color{White}, + breakatwhitespace=false, + breaklines=true, + captionpos=b, + keepspaces=true, + showspaces=false, + showstringspaces=false, + showtabs=false, + numbers=none, + frame=none, + tabsize=4, + defaultdialect=[LaTeX]Tex, +} +\lstset{style=kaolst}% Use the fancy style + +% Verbatim +%\RequirePackage{fancyvrb} % Customization of verbatim environments +%\fvset{fontsize=\normalsize} % Change here the font size of all +%verbatim \preto{\@verbatim}{\topsep=0pt \partopsep=0pt } + +% Algorithms +\RequirePackage[linesnumbered, ruled, vlined]{algorithm2e} % Algorithms + +% Special gliphs +\RequirePackage{ccicons} % Creative Commons icons + +% Index, glossary and nomenclature +\RequirePackage{imakeidx} +\RequirePackage[xindy,toc,numberedsection=nameref]{glossaries} +\RequirePackage[intoc]{nomencl} + +% Commands to print specific words always in the same way +% TODO: in \Command, automatically escape braces {} and replace backslashes with \textbackslash +\newcommand{\Class}[1]{\texttt{#1}} +\newcommand{\Package}[1]{\texttt{#1}} +\newcommand{\Option}[1]{\texttt{#1}} +\newcommand{\Command}[1]{\texttt{\textbackslash#1}} +\newcommand{\Environment}[1]{\texttt{#1}} +\newcommand{\Path}[1]{\texttt{#1}} + +% Print latin words in italics (The xspace package is required but we already loaded it in the class) +\newcommand{\hairsp}{\hspace{1pt}} % Command to print a very short space +\newcommand{\invitro}{\textit{in vitro}\xspace} +\newcommand{\invivo}{\textit{in vivo}\xspace} +\newcommand{\cis}{\textit{cis}\xspace} +\newcommand{\trans}{\textit{trans}\xspace} +\newcommand{\etal}{\textit{et al.}\xspace} +\newcommand{\denovo}{\textit{de novo}\xspace} +\newcommand{\adhoc}{\textit{ad hoc}\xspace} +\newcommand{\etcetera}{\textit{et cetera}\xspace} +\newcommand{\etc}{\textit{etc.}\xspace} +\newcommand{\ie}{\textit{i.\nobreak\hairsp{}e.}\xspace} +\newcommand{\eg}{\textit{e.\nobreak\hairsp{}g.}\xspace} +\newcommand{\vs}{\textit{vs}\xspace} +\newcommand{\cfr}{\textit{cfr.}\xspace} + +% Tables +\newcommand{\na}{\quad--} % Used in tables for N/A cells +\newcommand{\hangp}[1]{\makebox[0pt][r]{(}#1\makebox[0pt][l]{)}} % Create parentheses around text in tables which take up no horizontal space - this improves column spacing +\newcommand{\hangstar}{\makebox[0pt][l]{*}} % Create asterisks in tables which take up no horizontal space - this improves column spacing + +% A command to print the current month and year (from tufte-latex) +\newcommand{\monthyear}{\ifcase\month\or January\or February\or March\or +April\or May\or June\or July\or August\or September\or October\or +November\or December\fi\space\number\year} diff --git a/tex/kaobook.cls b/tex/kaobook.cls new file mode 100644 index 0000000..1563434 --- /dev/null +++ b/tex/kaobook.cls @@ -0,0 +1,282 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% kaobook +% LaTeX Class +% Version 0.9.8 (2021/08/23) +% +% This template originates from: +% https://www.LaTeXTemplates.com +% +% For the latest template development version and to make contributions: +% https://github.com/fmarotta/kaobook +% +% Authors: +% Federico Marotta (federicomarotta@mail.com) +% Based on the doctoral thesis of Ken Arroyo Ohori (https://3d.bk.tudelft.nl/ken/en) +% and on the Tufte-LaTeX class. +% Modified for LaTeX Templates by Vel (vel@latextemplates.com) +% +% License: +% LPPL (see included MANIFEST.md file) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%---------------------------------------------------------------------------------------- +% CLASS CONFIGURATION +%---------------------------------------------------------------------------------------- + +\NeedsTeXFormat{LaTeX2e} +\ProvidesClass{kaobook}[2021/08/23 v0.9.8 kaobook] +\newcommand{\@baseclass}{scrbook} % Base class name + +% Set the default options +\PassOptionsToClass{a4paper}{\@baseclass} +\PassOptionsToClass{fontsize=10pt}{\@baseclass} +\PassOptionsToClass{parskip=half}{\@baseclass} +\PassOptionsToClass{headings=optiontoheadandtoc}{\@baseclass} + +% Pass through any other options to the base class +\DeclareOption*{\PassOptionsToClass{\CurrentOption}{\@baseclass}} + +\ProcessOptions\relax % Process the options + +\LoadClass{\@baseclass} % Load the base class + +\RequirePackage{kao} % Load the code common to all classes + +%---------------------------------------------------------------------------------------- +% FRONT-, MAIN-, BACK- MATTERS BEHAVIOUR +%---------------------------------------------------------------------------------------- + +% Front matter +\let\oldfrontmatter\frontmatter % Store the old command +\renewcommand{\frontmatter}{% + \oldfrontmatter% First of all, call the old command + \pagestyle{plain.scrheadings}% Use a plain style for the header and the footer + \pagelayout{wide}% Use a wide page layout + \setchapterstyle{plain} % Choose the default chapter heading style + % \sloppy % Required to better break long lines +} + +%------------------------------------------------ + +% Main matter +\let\oldmainmatter\mainmatter % Store the old command +\renewcommand{\mainmatter}{% + \oldmainmatter% Call the old command + \pagestyle{scrheadings}% Use a fancy style for the header and the footer + \pagelayout{margin}% Use a 1.5 column layout + \setchapterstyle{kao} % Choose the default chapter heading style +} + +%------------------------------------------------ + +% Appendix +\let\oldappendix\appendix% Store the old command +\renewcommand{\appendix}{% + \oldappendix% Call the old command + \bookmarksetup{startatroot}% Reset the bookmark depth +} + +%------------------------------------------------ + +% Back matter +\let\oldbackmatter\backmatter% Store the old command +\renewcommand{\backmatter}{% + \oldbackmatter% Call the old command + \bookmarksetup{startatroot}% Reset the bookmark depth + \pagestyle{plain.scrheadings}% Use a plain style for the header and the footer + \pagelayout{wide}% Use a wide page layout + \setchapterstyle{plain} % Choose the default chapter heading style +} + +%---------------------------------------------------------------------------------------- +% CHAPTER HEADING STYLES +%---------------------------------------------------------------------------------------- + +% Command to easily switch between chapter styles +\DeclareDocumentCommand{\setchapterstyle}{m}{% + \ifthenelse{\equal{plain}{#1}}{\chapterstyleplain}{} + \ifthenelse{\equal{bar}{#1}}{\chapterstylebar}{} + \ifthenelse{\equal{lines}{#1}}{\chapterstylelines}{} + \ifthenelse{\equal{kao}{#1}}{\chapterstylekao}{} +} + +% The default definition in KOMA script +\DeclareDocumentCommand{\chapterstyleplain}{}{% + \renewcommand{\chapterlinesformat}[3]{% + \@hangfrom{##2}{##3}} + \renewcommand*{\chapterformat}{% + \mbox{\chapappifchapterprefix{\nobreakspace}\thechapter% + \autodot\IfUsePrefixLine{}{\enskip}}} + \RedeclareSectionCommand[beforeskip=0cm,afterskip=10\vscale]{chapter} + \setlength{\mtocshift}{-1\vscale} +} + +% Gray bar +\DeclareDocumentCommand{\chapterstylebar}{}{% + \renewcommand*{\chapterformat}{% + \mbox{\chapappifchapterprefix{\nobreakspace}\thechapter% + \autodot\IfUsePrefixLine{}{\enskip}}% + } + \renewcommand{\chapterlinesformat}[3]{% + \begin{tikzpicture}[remember picture, overlay] + \node[ + anchor=south west, + xshift=\dimexpr - \hoffset - \oddsidemargin - 1in -1mm,%-30\hscale, + yshift=4.3mm, + rectangle, + fill=gray!20!white, + fill opacity=0.8, + inner ysep=5\vscale, + inner xsep=\dimexpr \hoffset + \oddsidemargin + 1in,%30\hscale, + text opacity=1, + text width=\paperwidth-40\hscale, + ]{\@hangfrom{##2}{##3}}; + \end{tikzpicture} + } + \RedeclareSectionCommand[beforeskip=-55\vscale,afterskip=6\vscale]{chapter} + \setlength{\mtocshift}{-1\vscale} +} + +% Lines +\renewcommand{\hrulefill}[1][0.4pt]{% + \leavevmode\leaders\hrule height #1\hfill\kern\z@% +} +\DeclareDocumentCommand{\chapterstylelines}{}{% + \renewcommand*{\chapterformat}{% + \chapappifchapterprefix{\nobreakspace}\scalebox{3.5}{\thechapter\autodot}% + }% + \renewcommand\chapterlinesformat[3]{% + %\vspace*{-1cm}% + \leavevmode% + \makebox[0pt][l]{% + \makebox[\textwidth][l]{\hrulefill[1pt]##2}%\hfill%\par%\bigskip + \makebox[\marginparsep][l]{}% + \makebox[\marginparwidth][l]{}% + }\\ + %\vspace{.5cm} + \makebox[0pt][l]{% + \makebox[\textwidth][l]{##3}% + \makebox[\marginparsep][l]{}% + \makebox[\marginparwidth][l]{}% + }\\ + \makebox[0pt][l]{% + \makebox[\textwidth+\marginparsep+\marginparwidth][l]{\hrulefill[1.1pt]}% + }% + }% + \RedeclareSectionCommand[beforeskip=0cm,afterskip=10\vscale]{chapter} + \setlength{\mtocshift}{-1\vscale}% +} + +% The Kao style +\DeclareDocumentCommand{\chapterstylekao}{}{% + \IfWideLayout{% + \renewcommand*{\chapterformat}{% + \mbox{\chapappifchapterprefix{\nobreakspace}\scalebox{2.85}{\thechapter\autodot}}% + }% + \renewcommand\chapterlinesformat[3]{% + \vspace{3.5\vscale}% + \if@twoside% + \Ifthispageodd{% + \smash{\makebox[0pt][l]{% + \parbox[b]{\textwidth - 6.2\hscale}{\flushright{##3}}% + \makebox[6.2\hscale][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\marginparwidth}{##2}% + }}% + }{ + \smash{\makebox[\textwidth + 6.2\hscale][r]{% + \parbox[b]{47.7\hscale + 6.2\hscale}{\flushright{##2}}% + \makebox[6.2\hscale][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\textwidth}{\flushleft{##3}}% + }}% + } + \else% + \smash{\makebox[0pt][l]{% + \parbox[b]{\textwidth - 6.2\hscale}{\flushright{##3}}% + \makebox[6.2\hscale][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\marginparwidth}{##2}% + }}% + \fi% + }% + }{% + \renewcommand*{\chapterformat}{% + \mbox{\chapappifchapterprefix{\nobreakspace}\scalebox{2.85}{\thechapter\autodot}}% + }% + \renewcommand\chapterlinesformat[3]{% + \vspace{3.5\vscale}% + \if@twoside% + \Ifthispageodd{% + \smash{\makebox[0pt][l]{% + \parbox[b]{\textwidth}{\flushright{##3}}% + \makebox[\marginparsep][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\marginparwidth}{##2}% + }}% + }{ + \smash{\makebox[\textwidth][r]{% + \parbox[b]{\marginparwidth}{\flushright{##2}}% + \makebox[\marginparsep][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\textwidth}{\flushleft{##3}}% + }}% + } + \else% + \smash{\makebox[0pt][l]{% + \parbox[b]{\textwidth}{\flushright{##3}}% + \makebox[\marginparsep][c]{\rule[-2\vscale]{1pt}{27.4\vscale+\f@size mm}}% + \parbox[b]{\marginparwidth}{##2}% + }}% + \fi% + }% + }% + \RedeclareSectionCommand[beforeskip=0cm,afterskip=10\vscale]{chapter}% + \setlength{\mtocshift}{-3.5\vscale}% +} + +% Takes as input the image path and optionally the "beforeskip" +\DeclareDocumentCommand{\setchapterimage}{O{55\vscale} m}{% + \setchapterpreamble[o]{% + \vspace*{-27\vscale}\hspace*{\dimexpr - \hoffset - \oddsidemargin - 1in}% + \includegraphics[width=\paperwidth,height=#1+27\vscale,keepaspectratio=false]{#2}% + }% + \chapterstylebar% + % beforeskip=-(figure_height-top_margin) + \RedeclareSectionCommand[beforeskip=-#1, afterskip=6\vscale]{chapter}% + \setlength{\mtocshift}{0cm}% +} + +% By default start with the plain style +\chapterstyleplain + +%---------------------------------------------------------------------------------------- +% FONTS AND STYLES +%---------------------------------------------------------------------------------------- + +% Set KOMA fonts for book-specific elements +\addtokomafont{part}{\normalfont\scshape\bfseries} +\addtokomafont{partentry}{\normalfont\scshape\bfseries} +\addtokomafont{chapter}{\normalfont\bfseries} +\addtokomafont{chapterentry}{\normalfont\bfseries} + +% Set KOMA fonts for elements common to all classes +\addtokomafont{section}{\normalfont\bfseries} +\addtokomafont{subsection}{\normalfont\bfseries} +\addtokomafont{subsubsection}{\normalfont\bfseries} +\addtokomafont{paragraph}{\normalfont\bfseries} +\setkomafont{descriptionlabel}{\normalfont\bfseries} + +%---------------------------------------------------------------------------------------- +% TOC, LOF & LOT +%---------------------------------------------------------------------------------------- + +% Set default options regarding the table of contents +\PassOptionsToClass{toc=listof}{\@baseclass} +\PassOptionsToClass{toc=index}{\@baseclass} +\PassOptionsToClass{toc=bibliography}{\@baseclass} + +%---------------------------------------------------------------------------------------- +% NUMBERING +%---------------------------------------------------------------------------------------- + +%\setcounter{secnumdepth}{\kao@secnumdepth} % Set section numbering depth + +\counterwithin*{sidenote}{chapter} % Uncomment to reset the sidenote counter at each chapter +%\counterwithout{sidenote}{chapter} % Uncomment to have one sidenote counter for the whole document diff --git a/tex/main.pdf b/tex/main.pdf new file mode 100644 index 0000000000000000000000000000000000000000..482a5a7c91724ab5e0d0dd2d2e9d5e0709b93395 GIT binary patch literal 13399 zcmch81yEhd5@>=32`(W7xHu%py~xEOxVyW%ySsak03o=$I|&d7?(S~EHMo4(WOwu4 z+uHx@SM5@qd(P>ZX*u09)ji!qD#a&24WeO$C+!>mGS)sd^tA(?0RRM8>X^W@vjb@5 zoUQZ$v`UgXCi=Q|09sjl9lPHk0+u%B0NTgj-+F)mv^+ePP5{-1p+Eo#_~TLs(28r@ z*%&{74DE~n zAVvTuC*b!#cw0LgeQk4ir8u33-r$!7u}<}|2>`1J(|EjV_kIg|E?sD%j7>K z3HaZY&F9ShJ z&FGz}wAxoBIq}~2`Mn_a10sPG^{@qYJOao@2Aozg9%8ol!9**%!5+i2;qsH$F--o3 z_%*E#6J0~k5X3i|%cC(xCOn);Y0COuYSoO*8A;vRFT6Ym{4&ort%CDiy#LLoyz}!_ z`*+}otR=B-KAE^k-V$8x?aJ3j`?`d^hvOx4wbQVUBgexRx z5N@Xs)|mJVu9BCE_k3ABqGzRsnZV_9esEtM7T1I=5~FT1!A4u|QnLV^gv85aQhSy3 zHJ-QE&Ste#@G&`x`f|Dp1RdLnk;}Ni5s$3@^#&P#HI~2o#2^OHUw-21@XzqAZ&CcN zT|?Y`>^&{cD*!%G6h^MeQznE>o;&^tJVEbO-1=Ht+@P2M%p_NI*NFRhs)>>A;U3!tYbz@1&#q)qVhf8j!9QqP12U z6N;9V7I4dS$>GTp$$kjizaaGMivCA9z$?rrU}<6Z7z+S-|K6FWV|bWHf4K91GEl8x zDu-_PQsR{jx2_p|vI4n7K#i9};e^U8j5_VJZ4<`VSfTMmKGH!LYgkalWMgUubR=GI zM&({ZfcO^-QX~{w(y9exCe?4H%e9A1YG>zVX&0vkIU3QCiPX<`x2A0!Jo+v-J~AC# zvmc!FeT*DDIaxirbUWU&(pQq3dLxRaBcHzoCyZnKMm`_zBbi_x*pS3R=(|6a9^@2u zADR!|pl)jXp^^@iDABG`voczi#tPHjWatoh;b6aX6ngN)$!+?@BFE{LrlW|)nnGrY zFoZiUVKg8msPJs%N{m?d`hamUfsT>N*;K)#b>rgHtFzEpR`Vm+d1lPG6#5f-DZJCo ztk-&ew~4%(%UdG>7dIP|nON;o{Eg=?`mPVI({W>TYv0p|?J>)M~J zg{W7!2LOgqrSDFfIoLHOWQ*Wh_tZ5GN^0uhcM_xZQwG?J^T=|y&!%$PT)gfbwI&CR7fZRs8)U$8f<5FC0mRFRPd5F| z9J|(h139gFi+APCJj*py`6jaD2E3W?3XHp9rTK(95|gMdG4K*bk-s5HqEjXt?CT+@ zRn#;MmDJyAEu;<)Ac65mWA)zemEK*n;J;3N4Hy!Y^IoWdz5gohm|w#9{eA7|qIy%< zvt;tOuo@|4?t3Nlc)^=n z@-O*k9hvjYOP@XLV7wi8^tij|kf7J0Xc;Px#W?f62~0TyaAdv6v_q$p8w1m9pjG`E zpS$=*snOwvXm=GJk{%(6-c6XW1UbuJr1ZSfB|3GfB-5lV(ci|2ynd$s2Ci?ADSqpu z-L&Xs0nYvMC!<9{Qho>BrZ~S+Ul>Gi%lnLp!o?@eC$(RFIpUlL%r9W58p`(3Tw>f) z`devA*pKME&!DJf1~im$X48rAW?2S=*_iJQf^?Y-1ueh&(g-X-4<_G=o^Op!$XD|@ zWj^^lt+p`lfF%gK)CUVvI&Dqd8F!_1l8ox__Mw$eEm94YO!$b`pFQ6O)=kC)9q^Zg zEF=n(#XXB-*mam#N|_UP}d+yq(;jnp~ARwjSp8|`%AKBLDsi!~>c9EaMA z>k0O5`I_6jtqT0K3s&2E647P65&}z9g(+{sPcQ@gW#0F(ZdTi80n7L1eak z+vvBJhV6sotMffPBSbvPk^S=5&>n<2FC)l?*vcv8!am`5=+3ty3C>k;<=5~xHTG{1 zezD^MV9CdC5)ez(6mR(ITT>QfXJMeJm3B5>zDgpMeYhuD0@{6wJdWk!>ZYNyl|Gi!uIpOArFbPIB&4Fk)x z4&^&*moWC~<1EByT+oxWnc^)3ZV_AQBc~HcCjQ2ATEQ|o{**N4IidvbgUVj+)vN1N zOQ?|fwyXkOB>Ix=j%6nT5q|G% zJI$zUV#~QDFy=jMr3z9fcP+PJ6|d(KR-Ptsvjdqmy{&A}NG7O$05WDKA10qOzR-1; z0vvvVS@7-6nhggLfn+gLVa#emIIp{4CTkdUQVbTaeQr=F%?qsJ4EfWzbKMVhov%4; z@EXpUnhMXioU!DlvNl+2Qde_( z^)5$-0X%K+H(y@ukJ7Q%WQ0PhYkGz`AbBHsK6`n{=UQAfFZ7Kwe`2ynvS!zj>0N(H z4{hnvw@Am$JH~IH^UgC@pH(TAG9?<9tc6F5D;2lNs*`ff;=@1_3Ud$9zTqro4(+>{ zO3)1SZO@=9EH)xII+T1J9m6m{zC}el(-s~w2&&qeu@XlA2Ia!R^m0rxi9O9{m?B%>4<*R- zEQrlci#PasuEPSRizh0uC-g-mu)IdiOck_!D^I7s*La@o9oTTS^_<_(CyY2G?43|8yX%x$O8x$?IcjV)f;8RXrhB;tb*i zRnv*P;xng7h;0MOaMM@eW0|zOB9te1x*fcBZMa+VdE9}pj}ilw9)9+o@`y=PU_5*mZ(J3C(_f==4*_vp zI`zNK9@DRzLx1O0GJxs-^yz-_D#K&MEi-{A0S7nm2ZS;%X$g_LHS&J3Pojn_Mho}~ zHG(EeFNxmbag2yNGrpgqe&Wwyu=p`Lt)q znQe0?ay)_M6zqgOF2Xczd8aQOUyZTR5n|dsfF7v)-E$aAf~QGzj#bauYx2;ro>n9D zFrL{5%p;)-sbaT`kd$Lv$h+MKt35DrO3G1AbX*>Ek=4u{$P2nHo89g4xaidbZhp7BW~((!?UORgKelpz*sEju%OaE>$We z(&`Z1P%%4qSq*hMi}Jzldsx6Fmvu;qZlDqLiK!b`;8d!@H6Po@ppmQ|y!P_kSfXqp zxDj|t-Uh)2+gOX52s%@%s_*4g!5o;lk_n{LQXeuZD54ZnL_+*ndJ*&Ast~>xT8w&~ z#U}Zol(l#$KE0GjKcHtDb_5A-N3EUZtn2)1^=N50xI-4wd`Kii}#pDUyVD6d?&uCGjM zXe_JnM0IC}+rILTf@Z_}KVB8A{SgLc}5{#{AtG z^F*|kgRi-0n~j}LD<4d5 zd~{cmFLq=oLwpcORN(Y=>fT7FrMu`>4&x=+Gaz^%RvmLZdt3P>UdrP$(5* zu6a>H9*0h0tpjtU5>hXuxlf&yA8uWV3ookym%76ThcX_JIEk&Zi-O?Z@N5waqAC&D z*m`+Q8UPd3zJ;0?eMZLBb#|tqQFfLgacm4q4Rp{#F^^DKh#T5qJ0= zS40&B40M`ix)27;$vfISLL3S$K#0J-k1k1{vpZ#oplMq?04|#L7Nv$~WeS&oKIC#^ z`LOq}Q#%`74hZYv6Pre&GEchzP~9sl6S1Ej%Vra)%`q#Qk?`-61ib_f1*AEICUjY` z3|5`V8b;)lQt5~)A^7IxhHM&|g{T#(oEY59a_}K)QuY3Jb0?1dG z?PHG--@_n~p8TZ)LWt<2Dquk~K|_wuP)~1dCvW}(d4&DMX`{&t{}kIVMA&_Hlw2^H z&%CCc{JD-usho>$U&BVq#9P?Aoo+`&;4y}Yi_}Fpq9aJN<|vs1YB=kkxeDn$j9hi>+u!SJt-~amwd^%a~|& zZkL$BSbrrR2I23b6j<63%LJUf!hOeEkjykUYZMvfu5;zG>jMc|j6t}QK zgU1{rZ*snlbX+>E!u+vRKXo`-Jl!rByvbQ*rE2s}q}-bemH?3=^2@7vMklD*7qFhS z*ue&C>>oeJlI>&dh+ls>)PT*JtGvRH{_t?1k#a-0Lz9Uhw%| z0l7=oE28HUrCnc*?7JmIJ{RV+x9EX49h2nU$u4&}A`E-1(E7!$5UHmcKujzt3Z~Ia zoSE>Zb3@poZ9Y@IXQI;V(6)9tH8)AWCh1Da2Jw1)7Y!rtHexfdiZDc zslMXMB6Y#Om|IOy(0Y!G#awgst?#eVgw4P%ev`80JFAK&4g?gGdI(A%E00D4wdFbLdx5WYS}yKsMVdwVrTfM4qTgvhO+*@okP0$PzReSfDfx z%iqqr^|#*=H!;iLEEkxq;B^=R`!O{bP<96LD}T-Yw2<(|gDo;hw#o$dZi#J;?CZ!#A9-yZQfZ-S9?GkFT1yQtW(ot9pPfD-82*NXcD(K z(LTEhK)Qdop*6dOKb{O7h&>FC%Z6p_=Xy|~Eb_{3$`5i8$yI5D&>L`(I~CVT-k#4x zaLB%`Jtzo*Q&7At3-mj)6rzYulmBK~zMhqRTeVG1iE2L&mf~C)rcQ|sB5xO?`!0ol zVp!%)b0c%q8cVWpP64rSM6ojFNAwDrLI+ZTZ`+X~V?&$Y?@kge)a0Du{z)(gNReFF zY)*z$mR(byegDfvo@h%2sla`NHVrfcCwVH3S_(Qpx;)GFD{(iEWs60~aYKZiybhK0 zJ>V#d4GLeGjJ)z*UiLL<^;t9o>?%+R(nj7|hDZl~1>z1PVCojY7jM@GR^b#=wF1N+ zvlPV%M4{~sbjRc}^v9*kQoeQWn)=2v$9eOu9@kAlcLMcB-op)P-dh z@>wNlV|VnGXMe08C+)oviNh@IiY%+ZH@hKBFR!=J*?}akaonrD#pom-FsU}h-R+dQ zeG_N$%z?On9vXs$-|4HbAG&c&tS!aY*U4y_m<0ZtM$Lk5d@m2adOQ~saI0vUP%2HheuB1(!?x3{`_KsP|p(`?5tLf3O*Dj<(Yb$ z8SQ01oe<^^4qAArdaFu{$4c7r@8B7=oCD_sjh9@3Jx!MEm&Jl?9cLvOH1M&h9#3sM z=rqE&bzdURY`+MZ!ffO`fM(=V;H+Gx|KYBMfHU>_~^ER{dG53rTF?qMCINxaUDC?T-TAfpcdKw=Q9uV{pRO9 z_Hh;1HyjNnjdtxYJ*~55QFXt8s^k_?d#1zNACo5L z)@W5Q2q}W{bt4Lrd1^EJgCJXI1Etf=ZSzu%c-1}vgRQPw1ZVPPqn%it)Di36k{^#t zt#h()e?^fcf029tYs@Tm;f12R_KMul6n8q}>|H%FNb!-F@Z|S`ly>;H;c6Clr)RK? zOp9zTtwol4Qkiy+3MLxx*-FxucBTEt7FO6nS_np6(P&kO?ZI#Sk(w$-x)pmM*#a8W z)UjDLw`L~r2@5exj_j*HyA`tocdz0ciAy%|&ioCvDw$Im4>xXJaBAWwpuMjmrewV| z6KS@18`s-$Qtvu>fo3Kn|rry(akLO1Nk|6Y=OA!{5k|w0eD%Io}T*)h&Z6U=}%nJcoDcHfqNCz zHD^iL0{ByNiuT9vWF1QKGa6G1fFeQeU*i0H`qAUFxtm0-9FjUvikT_e;+AXW4}=!W zQ%V!^)ZM5)R@u8|us@+5{#+GIcxL`71CL?!Q14B>1X}Xw)=MK!m!{kr5`SqYi$N|2 z+2hpZH)Ys+^+<-V#mD!T60by@iYhWU__Coe<%FFt5ho*C90O*>?{GDW&?o*PRQWY` z|Fe7uShvtJ@bg7%hY&%=nju%H$Nc?^v?D(2P2 zdG#$>qs+K@)LZtxFlPhy4{pxW{-VkR6k--EuGuyF;{4i2O5iVg6$OQNJPocy(IlNl z*DV@i>U(**qdJWzD|?%@hmEZ7wqo~Z z)$?b8rGs>9C03;kmDCrOG?j3>Cr}&6uEe7SDqLk3akdtoN~X$V*pnu>e7-cH9WW6h zqV&v_zB_;*L$QJa+%8WAY&LquPmMKr>NQtNu%XbQ8s=qtedCRbP{Wl`da<14Tbqes z^GT-u4@qdN+;JdbLDz=lNm*w?tV1I$1dx{$vzoX%^bZ?Fg(@<$v6vrZQYnE|8%0}gz^{oDAT?I6$(e8AuFgXt(~ z<&5pj^#6+w`p0p<&;kD(_XoZo{D6RT|3&u)y+8Q)$^V~x{MEQW>41Qb?SH=iJ`VU( zo`*`qAN0UK@4tPIKjj7ie}2c`<@@h;(9iZi_U7Yf6)Jr@sIR> z>gy+8AmD%M3G}F&-}LjJ`T+ip=MQ;)>hpI!{lp6b{jTT#!uz{C;2(1R-Vez1yIy|k z<5ABK8!3-fofMR`yblGHb`Q2ErY)zh1aLHdsJS$HNafnt=o?Vdit0N%TH5H@QcwbD zrEDzq>~$aNG%3XFANxL(j)ItJfDbLdp)j_z;Cm?F1W@p?(gEohfM6gqh@O#&p79Nk zo*W1yf9NM}srP^DB4?v*Wu>q8kVe)vvwf%nm6GFEq7kq+Gvm>=uy~{`XJl*(c=&(d zL5Syp3o3wuzK!hzalj9D9(p{8A!h8L4|rsQmfJ?x=;77E-iea(VHfCe(SDqCzpm6j z>RcstOl0jI>RKfL49t&NY#UoUz{6Dh`-C=#`JvG8FA~~&D$16#9atWdrOc6MpMfm& zNtn-kcCv-T>LRpr%~jfws~Dt%-o!u%Lw7eHu(a`qVyXtKr0eG~fPbMR zrS`<|LQ^QMM1;W#!AJOJ2@osqB?^ZP;pffw1{MyIl1c*pU0g3W5jQDX=gU||G!j^9 zoEnJPuRd~V@A=5Wse58zs>lf8Y6QHa)56;(ydBgKF^<{P6d@2tVPau?VZ7<4L;^+1 z?6WY$qM4VpNO}ZJf{Wl7^MbW^*50mG@vPcI#DOZF%=%G1>4i37&_eeXU?~$JM29Vu zu0z$LW;I5$Li_;2mr!B^!X)vzkk}_?nj}rWY_}j|bwps28KLEC zI0$IEN{Fa*gAgZ(%USUF;A}_ANt46x%qS{|zk+^GiF?@_FE~YQF-jFk80s?@1ftnx zjKW^8Guen&@LHY;b>=LnBtkZ6;2w%`Q`ZszF01UCX)`P|?1P4Jl~-15#6$WD@_^DETc)1sV!rTxuKDojWTM5M(^n@r#>H|;f{HCt7ua&92(h1fxBrsT z=)R$=w9m~E&sA}M-+UwR4!la+HZD-#cs{EhG3CBm-izv)`ReIW?~1v1&T2FU#V*=> z&o(swA$5}wc}fkNAf`RE3^+Ev>Gj5Xm*Od#Ov2@KWaVkzMc4{OKu^BV&>(ZP;Kb|W zeIjaUm|F*4#Ns&p?*|_DkX506wpuKaXx)UVlDP;m6T#0Bz6$gTS=~Nc!Mv$OQqQvA z>wTqy`eH3!(O%^msq+ zO=#iWT^vMi#9DTjdD%Y5cGYdAFAY$j+`JG`B(QZQ`Oz zKH))i*{O8mde&wyB42D;;Sqp44dCotGb6VUSFclp4w#hO;dwEbqK4U(h%lP)m$_{= zToDORDK4MasgZf0#LuE};n5KItgJwi_K^`7tgpcYe6DDx*OrBuF06Ff{`dsxY=K;0 zHPv}A!EF#NoZ5Ae#I!>NTs)k<9#&gyw8_T$nH4;HNPWt%BkH2cnG@sid33b65Ys)W z`pmT2Ir$@F<5Xg*PCtG*QR!rJYjc*MqnnBNfXl0iwbQ#Q51V?T_!GU#xd8%mg>MO{ zrbp=4zF%$)jfkPJ(htOT#K(2aJ#4$I@#T@9a*HoQ)BDjd#jY{xbM9Z2EQOYAH`2gi zBp{VV!eNfajg2vdZG=O1e*_f^<9rLt88vD9M9LbT%AgS7&di{I%W~Jl(BalBJdK(cVX}IKU(GBelCwliZ7z(HmaW3ed5Eyt;??=QeBW)pJ4*-a-11Rt;=_cRF+M z$1Bwtj0w)jAvPc7R_H53ey=# zxw$7DsnjtcvLTzX@VFE(My7#+r&yxw@1Z>QAjFjrI=?bUn6ig$Q5Eo+g&&S)u4>*p zeSWpdP>K{0vUOqlEiPav{L6-L-86CZ^^$q5Pc5dVf35VJL-29_l6&eVZkjpxt*R$e z)xq=YZG#V4zSXFb$UEa#weal&uO_W|H4K*-^QaeRO^l0;Jm^bvl_T6PW@Ho?=WpT3 zQnDG05Q-#pI)&}w=Xp#+bQ|I)Cgjphz~;|ArLQEDKgmlB+g5}pZOX}PVWy!>b$|FA zqhsgwUPbv}RG&RV$=RYn;A={0=Dh1XX@=N7O8<^(ap_c+oo?`19{7{pStnLJcD zT(MFIEei?T2ISQ^Jw3$Rw?2LtME-d2T#w+A>nWh7fcAf*CFZ}VMU~Mv0MH6s=;{AB zPQuIpcsMU2YwV&AczC2${Ov3W-NSj3$5SMhmUaNqOVqQjCsELjBr*Vq61Av+X5`d@vF-CQ zndSn@={8P-3BIgPmoeY*=Fe31`l~y;8W{4j2nAj!mMnIBBGiA68?g|Zb6WZ>n4xga zEj&epe|?S6rFV<9V(*lxVs%1LPf_LAG8hx%{QFR6+$?Q5eG3Y4Ec2I_=(}1W=8hgZ zOl>qaVb)%@edR4UNY;M3j$G>t)k*!UdzA20$&1~WjcRk9ZvM|{tb*UfOCI-E-aXX{ g0G#}<25s%MZS0&L97T8#9Sa>3JSi!^qyYT?0j$k}&j0`b literal 0 HcmV?d00001 diff --git a/tex/main.tex b/tex/main.tex new file mode 100644 index 0000000..48a4894 --- /dev/null +++ b/tex/main.tex @@ -0,0 +1,21 @@ +\documentclass[ + a4paper, + twoside=false +]{kaobook} + +\input{styles/language.tex} + +\title{О достижимости с ограничениями в терминах формальных языков} +\author{Семён Григорьев} +\date{\today} + +\begin{document} + +\frontmatter + +\maketitle +\tableofcontents + +\mainmatter + +\end{document} diff --git a/tex/styles/language.tex b/tex/styles/language.tex new file mode 100644 index 0000000..1133a38 --- /dev/null +++ b/tex/styles/language.tex @@ -0,0 +1,3 @@ +\usepackage{polyglossia} % Локализация документа --- переносы и всё такое +\setmainlanguage{russian} +\setotherlanguage{english} From 376c0ea2d253cec9fb26009f0818a8a4a3c9405e Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sat, 8 Jun 2024 14:37:24 +0300 Subject: [PATCH 04/29] Add list of contributors Changed list type, made emails clickable and added xurl to break urls at any letter --- tex/List_of_contributors.tex | 19 +++++++++++++++++++ tex/main.tex | 3 +++ tex/styles/utils.tex | 3 +++ 3 files changed, 25 insertions(+) create mode 100644 tex/List_of_contributors.tex create mode 100644 tex/styles/utils.tex diff --git a/tex/List_of_contributors.tex b/tex/List_of_contributors.tex new file mode 100644 index 0000000..ae6d48e --- /dev/null +++ b/tex/List_of_contributors.tex @@ -0,0 +1,19 @@ +\addchap{Список авторов} + +\begin{description}[style=nextline] + \item[Семён Григорьев] + Санкт-Петербургский государственный университет, Университетская набережная, 7/9, Санкт-Петербург, 199034, Россия \\ + \email{s.v.grigoriev@spbu.ru}\\ + JetBrains Research, Приморский проспект 68-70, здание 1, Санкт-Петербург, 197374, Россия \\ + \email{semyon.grigorev@jetbrains.com} + \item[Екатерина Вербицкая] + JetBrains Research, Приморский проспект 68-70, здание 1, Санкт-Петербург, 197374, Россия \\ + \email{ekaterina.verbitskaya@jetbrains.com} + \item[Дмитрий Кутленков] + Санкт-Петербургский государственный университет, Университетская набережная, 7/9, Санкт-Петербург, 199034, Россия \\ + \email{kutlenkov.dmitri@gmail.com} + \item[] +\end{description} + +Полный список людей, внёсших свой вклад в данную работу, можно посмотреть на страничке проекта: +\url{https://github.com/FormalLanguageConstrainedPathQuerying/FormalLanguageConstrainedReachability-LectureNotes} diff --git a/tex/main.tex b/tex/main.tex index 48a4894..e208bcb 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -4,6 +4,7 @@ ]{kaobook} \input{styles/language.tex} +\input{styles/utils.tex} \title{О достижимости с ограничениями в терминах формальных языков} \author{Семён Григорьев} @@ -16,6 +17,8 @@ \maketitle \tableofcontents +\input{List_of_contributors} + \mainmatter \end{document} diff --git a/tex/styles/utils.tex b/tex/styles/utils.tex new file mode 100644 index 0000000..1541c1b --- /dev/null +++ b/tex/styles/utils.tex @@ -0,0 +1,3 @@ +\usepackage{xurl} % Разрешить переносить URL на любой букве + +\NewDocumentCommand{\email}{m}{\href{mailto:#1}{#1}} % Кликабельный email From 50f025557bcc62e868c99ac2f8c9eddca7a7f419 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sat, 8 Jun 2024 18:46:35 +0300 Subject: [PATCH 05/29] Add introduction chapter Replaced \cite with \sidecite --- ...ageConstrainedReachabilityLectureNotes.bib | 2007 +++++++++++++++++ tex/Introduction.tex | 78 + tex/kaobiblio.sty | 426 ++++ tex/main.tex | 12 + 4 files changed, 2523 insertions(+) create mode 100644 tex/FormalLanguageConstrainedReachabilityLectureNotes.bib create mode 100644 tex/Introduction.tex create mode 100644 tex/kaobiblio.sty diff --git a/tex/FormalLanguageConstrainedReachabilityLectureNotes.bib b/tex/FormalLanguageConstrainedReachabilityLectureNotes.bib new file mode 100644 index 0000000..2548972 --- /dev/null +++ b/tex/FormalLanguageConstrainedReachabilityLectureNotes.bib @@ -0,0 +1,2007 @@ +@article{cohen2016parsing, + title = {Parsing linear context-free rewriting systems with fast matrix multiplication}, + author = {Cohen, Shay B and Gildea, Daniel}, + journal = {Computational Linguistics}, + volume = {42}, + number = {3}, + pages = {421--455}, + year = {2016}, + publisher = {MIT Press One Rogers Street, Cambridge, MA 02142-1209, USA journals-info~…} +} + +@inproceedings{nakanishi1997efficient, + title = {An efficient recognition algorithm for multiple context-free languages}, + author = {Nakanishi, Ryuichi and Takada, Keita and Seki, Hiroyuki}, + booktitle = {In Proceedings of the Fifth Meeting on Mathematics of Language, MOL5}, + year = {1997}, + organization = {Citeseer} +} + +@inproceedings{zhang2013fast, + title = {Fast algorithms for Dyck-CFL-reachability with applications to alias analysis}, + author = {Zhang, Qirun and Lyu, Michael R and Yuan, Hao and Su, Zhendong}, + booktitle = {Proceedings of the 34th ACM SIGPLAN Conference on Programming Language Design and Implementation}, + pages = {435--446}, + year = {2013} +} + +@article{kodumal2004set, + title = {The set constraint/CFL reachability connection in practice}, + author = {Kodumal, John and Aiken, Alex}, + journal = {ACM Sigplan Notices}, + volume = {39}, + number = {6}, + pages = {207--218}, + year = {2004}, + publisher = {ACM New York, NY, USA} +} + +@article{reps2000undecidability, + title = {Undecidability of context-sensitive data-dependence analysis}, + author = {Reps, Thomas}, + journal = {ACM Transactions on Programming Languages and Systems (TOPLAS)}, + volume = {22}, + number = {1}, + pages = {162--186}, + year = {2000}, + publisher = {ACM New York, NY, USA} +} + +@inproceedings{yan2011demand, + title = {Demand-driven context-sensitive alias analysis for Java}, + author = {Yan, Dacong and Xu, Guoqing and Rountev, Atanas}, + booktitle = {Proceedings of the 2011 International Symposium on Software Testing and Analysis}, + pages = {155--165}, + year = {2011} +} + +@inproceedings{bastani2015specification, + title = {Specification inference using context-free language reachability}, + author = {Bastani, Osbert and Anand, Saswat and Aiken, Alex}, + booktitle = {Proceedings of the 42nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages}, + pages = {553--566}, + year = {2015} +} + +@inproceedings{zheng2008demand, + title = {Demand-driven alias analysis for C}, + author = {Zheng, Xin and Rugina, Radu}, + booktitle = {Proceedings of the 35th annual ACM SIGPLAN-SIGACT symposium on Principles of programming languages}, + pages = {197--208}, + year = {2008} +} + +@inproceedings{huang2015scalable, + title = {Scalable and precise taint analysis for android}, + author = {Huang, Wei and Dong, Yao and Milanova, Ana and Dolby, Julian}, + booktitle = {Proceedings of the 2015 International Symposium on Software Testing and Analysis}, + pages = {106--117}, + year = {2015} +} + +@article{sridharan2006refinement, + title = {Refinement-based context-sensitive points-to analysis for Java}, + author = {Sridharan, Manu and Bod{\'\i}k, Rastislav}, + journal = {ACM SIGPLAN Notices}, + volume = {41}, + number = {6}, + pages = {387--400}, + year = {2006}, + publisher = {ACM New York, NY, USA} +} + +@inproceedings{zhang2017context, + title = {Context-sensitive data-dependence analysis via linear conjunctive language reachability}, + author = {Zhang, Qirun and Su, Zhendong}, + booktitle = {Proceedings of the 44th ACM SIGPLAN Symposium on Principles of Programming Languages}, + pages = {344--358}, + year = {2017} +} + +@article{seki1991multiple, + title = {On multiple context-free grammars}, + author = {Seki, Hiroyuki and Matsumura, Takashi and Fujii, Mamoru and Kasami, Tadao}, + journal = {Theoretical Computer Science}, + volume = {88}, + number = {2}, + pages = {191--229}, + year = {1991}, + publisher = {Elsevier} +} + +@book{Hopcroft+Ullman/79/Introduction, + added-at = {2009-05-20T01:29:36.000+0200}, + author = {Hopcroft, John E. and Ullman, Jeff D.}, + biburl = {https://www.bibsonomy.org/bibtex/26f42b10773b0f97be73d4e0d6b8db3bf/sriram0339}, + description = {First cut database}, + interhash = {0fb20598f4921085d9c5058fc8d95f00}, + intrahash = {6f42b10773b0f97be73d4e0d6b8db3bf}, + keywords = {imported}, + publisher = {Addison-Wesley Publishing Company}, + timestamp = {2009-05-20T01:29:37.000+0200}, + title = {Introduction to Automata Theory, Languages, and Computation}, + year = 1979 +} + +@inproceedings{Verbitskaia:2018:PCC:3241653.3241655, + author = {Verbitskaia, Ekaterina and Kirillov, Ilya and Nozkin, Ilya and Grigorev, Semyon}, + title = {Parser Combinators for Context-free Path Querying}, + booktitle = {Proceedings of the 9th ACM SIGPLAN International Symposium on Scala}, + series = {Scala 2018}, + year = {2018}, + isbn = {978-1-4503-5836-1}, + location = {St. Louis, MO, USA}, + pages = {13--23}, + numpages = {11}, + url = {http://doi.acm.org/10.1145/3241653.3241655}, + doi = {10.1145/3241653.3241655}, + acmid = {3241655}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {Context-Free Language Reachability, Context-Free Path Querying, GLL, Generalized LL, Graph Databases, Language-Constrained Path Problem, Neo4j, Parser Combinators, Scala} +} + +@inproceedings{Mishin:2019:ECP:3327964.3328503, + author = {Mishin, Nikita and Sokolov, Iaroslav and Spirin, Egor and Kutuev, Vladimir and Nemchinov, Egor and Gorbatyuk, Sergey and Grigorev, Semyon}, + title = {Evaluation of the Context-Free Path Querying Algorithm Based on Matrix Multiplication}, + booktitle = {Proceedings of the 2Nd Joint International Workshop on Graph Data Management Experiences \& Systems (GRADES) and Network Data Analytics (NDA)}, + series = {GRADES-NDA'19}, + year = {2019}, + isbn = {978-1-4503-6789-9}, + location = {Amsterdam, Netherlands}, + pages = {12:1--12:5}, + articleno = {12}, + numpages = {5}, + url = {http://doi.acm.org/10.1145/3327964.3328503}, + doi = {10.1145/3327964.3328503}, + acmid = {3328503}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {CUDA, Context-free path querying, GPGPU, boolean matrix, context-free grammar, graph databases, matrix multiplication, transitive closure} +} + +@article{Valiant:1975:GCR:1739932.1740048, + author = {Valiant, Leslie G.}, + title = {General Context-free Recognition in Less Than Cubic Time}, + journal = {J. Comput. Syst. Sci.}, + issue_date = {April, 1975}, + volume = {10}, + number = {2}, + month = apr, + year = {1975}, + issn = {0022-0000}, + pages = {308--315}, + numpages = {8}, + url = {http://dx.doi.org/10.1016/S0022-0000(75)80046-8}, + doi = {10.1016/S0022-0000(75)80046-8}, + acmid = {1740048}, + publisher = {Academic Press, Inc.}, + address = {Orlando, FL, USA} +} + +@inproceedings{Yannakis, + author = {Yannakakis, Mihalis}, + year = {1990}, + month = {01}, + pages = {230-242}, + title = {Graph-Theoretic Methods in Database Theory.}, + doi = {10.1145/298514.298576} +} + +@inproceedings{Azimov:2018:CPQ:3210259.3210264, + author = {Azimov, Rustam and Grigorev, Semyon}, + title = {Context-free Path Querying by Matrix Multiplication}, + booktitle = {Proceedings of the 1st ACM SIGMOD Joint International Workshop on Graph Data Management Experiences \& Systems (GRADES) and Network Data Analytics (NDA)}, + series = {GRADES-NDA '18}, + year = {2018}, + isbn = {978-1-4503-5695-4}, + location = {Houston, Texas}, + pages = {5:1--5:10}, + articleno = {5}, + numpages = {10}, + url = {http://doi.acm.org/10.1145/3210259.3210264}, + doi = {10.1145/3210259.3210264}, + acmid = {3210264}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {GPGPU, context-free grammar, context-free path querying, graph databases, matrix multiplication, transitive closure} +} + +@inproceedings{Grigorev:2017:CPQ:3166094.3166104, + author = {Grigorev, Semyon and Ragozina, Anastasiya}, + title = {Context-free Path Querying with Structural Representation of Result}, + booktitle = {Proceedings of the 13th Central \& Eastern European Software Engineering Conference in Russia}, + series = {CEE-SECR '17}, + year = {2017}, + isbn = {978-1-4503-6396-9}, + location = {St. Petersburg, Russia}, + pages = {10:1--10:7}, + articleno = {10}, + numpages = {7}, + url = {http://doi.acm.org/10.1145/3166094.3166104}, + doi = {10.1145/3166094.3166104}, + acmid = {3166104}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {CFPQ, GLL, LL, context-free grammar, graph database, graph parsing, path query, top-down parsing} +} + +@inproceedings{Kuijpers:2019:ESC:3335783.3335791, + author = {Kuijpers, Jochem and Fletcher, George and Yakovets, Nikolay and Lindaaker, Tobias}, + title = {An Experimental Study of Context-Free Path Query Evaluation Methods}, + booktitle = {Proceedings of the 31st International Conference on Scientific and Statistical Database Management}, + series = {SSDBM '19}, + year = {2019}, + isbn = {978-1-4503-6216-0}, + location = {Santa Cruz, CA, USA}, + pages = {121--132}, + numpages = {12}, + url = {http://doi.acm.org/10.1145/3335783.3335791}, + doi = {10.1145/3335783.3335791}, + acmid = {3335791}, + publisher = {ACM}, + address = {New York, NY, USA} +} + +@article{MEDEIROS201975, + title = {LL-based query answering over RDF databases}, + journal = {Journal of Computer Languages}, + volume = {51}, + pages = {75 - 87}, + year = {2019}, + issn = {2590-1184}, + doi = {https://doi.org/10.1016/j.cola.2019.02.002}, + url = {http://www.sciencedirect.com/science/article/pii/S1045926X18301915}, + author = {Ciro M. Medeiros and Martin A. Musicante and Umberto S. Costa}, + keywords = {Context-Free graph patterns, Graph databases, RDF, SPARQL}, + abstract = {We present a method based on top-down parsing techniques for evaluating context-free path queries on RDF Graph Databases. The syntax of the query language is based on SPARQL. The language extends SPARQL by allowing the use of non-terminal symbols of a context-free grammar to specify paths on the graph. In this manner, the language subsumes the definition of regular graph patterns present in SPARQL. Our query evaluator takes an RDF graph, a context-free grammar and a declarative query, and produces tuples of values. The query evaluator proceeds in two stages: Firstly, the RDF graph is enriched with edges representing paths which correspond to strings derived by the grammar. We show that this algorithm is correct and presents a cubic worst-case run-time complexity on the number of nodes in the graph, which is an improvement over some previous work. The second stage of the evaluator uses the produced graph to identify tuples of values defined by a declarative query. In order to validate our approach, we conducted experiments by using some popular ontologies as well as synthetic databases. We compare performance results of our method with some related work.} +} + + +@inproceedings{8249039, + author = {P. G. {Bradford}}, + booktitle = {2017 IEEE 8th Annual Ubiquitous Computing, Electronics and Mobile Communication Conference (UEMCON)}, + title = {Efficient exact paths for dyck and semi-dyck labeled path reachability (extended abstract)}, + year = {2017}, + volume = {}, + number = {}, + pages = {247-253}, + keywords = {computational complexity;directed graphs;formal languages;graph theory;matrix multiplication;reachability analysis;efficient exact paths;weighted digraph;exact path length problem;exact path problem;original edge weights;path solutions;labeled digraph;semiDyck languages;Dyck languages;labeled path problems;Grammar;Heuristic algorithms;Jacobian matrices;Costing;Algorithm design and analysis;Shortest path problem}, + doi = {10.1109/UEMCON.2017.8249039}, + issn = {}, + month = {Oct} +} + +@article{quadtree, + author = {El abbadi, Nidhal}, + year = {2014}, + month = {11}, + pages = {25-30}, + title = {An Efficient Storage Format for Large Sparse Matrices based on Quadtree}, + volume = {105}, + journal = {International Journal of Computer Applications} +} + +@inproceedings{10.1007/978-3-319-41579-6_22, + author = {Verbitskaia, Ekaterina + and Grigorev, Semyon + and Avdyukhin, Dmitry}, + editor = {Mazzara, Manuel + and Voronkov, Andrei}, + title = {Relaxed Parsing of Regular Approximations of String-Embedded Languages}, + booktitle = {Perspectives of System Informatics}, + year = {2016}, + publisher = {Springer International Publishing}, + address = {Cham}, + pages = {291--302}, + abstract = {We present a technique for syntax analysis of a regular set of input strings. This problem is relevant for the analysis of string-embedded languages when a host program generates clauses of embedded language at run time. Our technique is based on a generalization of RNGLR algorithm, which, inherently, allows us to construct a finite representation of parse forest for regularly approximated set of input strings. This representation can be further utilized for semantic analysis and transformations in the context of reengineering, code maintenance, program understanding etc. The approach in question implements relaxed parsing: non-recognized strings in approximation set are ignored with no error detection.}, + isbn = {978-3-319-41579-6} +} + +@article{Lee:2002:FCG:505241.505242, + author = {Lee, Lillian}, + title = {Fast Context-free Grammar Parsing Requires Fast Boolean Matrix Multiplication}, + journal = {J. ACM}, + issue_date = {January 2002}, + volume = {49}, + number = {1}, + month = jan, + year = {2002}, + issn = {0004-5411}, + pages = {1--15}, + numpages = {15}, + url = {http://doi.acm.org/10.1145/505241.505242}, + doi = {10.1145/505241.505242}, + acmid = {505242}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {Boolean matrix multiplication, context-free grammar parsing} +} + +@article{Chan2008, + author = {Chan, Timothy M.}, + title = {All-Pairs Shortest Paths with Real Weights in $O(n^3/log{\thinspace}n)$ Time}, + journal = {Algorithmica}, + year = {2008}, + month = {Feb}, + day = {01}, + volume = {50}, + number = {2}, + pages = {236--243}, + issn = {1432-0541}, + doi = {10.1007/s00453-007-9062-1}, + url = {https://doi.org/10.1007/s00453-007-9062-1} +} + +@inproceedings{Williams:2010:SEP:1917827.1918339, + author = {Williams, Virginia Vassilevska and Williams, Ryan}, + title = {Subcubic Equivalences Between Path, Matrix and Triangle Problems}, + booktitle = {Proceedings of the 2010 IEEE 51st Annual Symposium on Foundations of Computer Science}, + series = {FOCS '10}, + year = {2010}, + isbn = {978-0-7695-4244-7}, + pages = {645--654}, + numpages = {10}, + url = {http://dx.doi.org/10.1109/FOCS.2010.67}, + doi = {10.1109/FOCS.2010.67}, + acmid = {1918339}, + publisher = {IEEE Computer Society}, + address = {Washington, DC, USA}, + keywords = {all pairs shortest paths, subcubic algorithms, equivalences, reductions, matrix multiplication, triangle detection, minimum cycle, replacement paths} +} + +@inproceedings{Kroni:2013:PGA:2489837.2489844, + author = {Kr\"{o}ni, Daniel and Schweizer, Raphael}, + title = {Parsing Graphs: Applying Parser Combinators to Graph Traversals}, + booktitle = {Proceedings of the 4th Workshop on Scala}, + series = {SCALA '13}, + year = {2013}, + isbn = {978-1-4503-2064-1}, + location = {Montpellier, France}, + pages = {7:1--7:4}, + articleno = {7}, + numpages = {4}, + url = {http://doi.acm.org/10.1145/2489837.2489844}, + doi = {10.1145/2489837.2489844}, + acmid = {2489844}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {Scala, domain specific language, graph database, graph traversal, parser combinators} +} + +@inproceedings{Reps, + author = {Reps, Thomas}, + title = {Program Analysis via Graph Reachability}, + booktitle = {Proceedings of the 1997 International Symposium on Logic Programming}, + series = {ILPS '97}, + year = {1997}, + isbn = {0-262-63180-6}, + location = {Port Washington, New York, USA}, + pages = {5--19}, + numpages = {15}, + url = {http://dl.acm.org/citation.cfm?id=271338.271343}, + acmid = {271343}, + publisher = {MIT Press}, + address = {Cambridge, MA, USA} +} + +@inproceedings{LabelFlowCFLReachability, + title = {Existential label flow inference via CFL reachability}, + author = {Pratikakis, Polyvios and Foster, Jeffrey S and Hicks, Michael}, + booktitle = {SAS}, + volume = {6}, + pages = {88--106}, + year = {2006}, + organization = {Springer} +} + +@inproceedings{Yannakakis, + title = {Graph-theoretic methods in database theory}, + author = {Yannakakis, Mihalis}, + booktitle = {Proceedings of the ninth ACM SIGACT-SIGMOD-SIGART symposium on Principles of database systems}, + pages = {230--242}, + year = {1990}, + organization = {ACM} +} + +@inproceedings{specificationCFLReachability, + title = {Specification inference using context-free language reachability}, + author = {Bastani, Osbert and Anand, Saswat and Aiken, Alex}, + booktitle = {ACM SIGPLAN Notices}, + volume = {50}, + number = {1}, + pages = {553--566}, + year = {2015}, + organization = {ACM} +} + +@inproceedings{Zheng, + author = {Zheng, Xin and Rugina, Radu}, + title = {Demand-driven Alias Analysis for C}, + booktitle = {Proceedings of the 35th Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages}, + series = {POPL '08}, + year = {2008}, + isbn = {978-1-59593-689-9}, + location = {San Francisco, California, USA}, + pages = {197--208}, + numpages = {12}, + url = {http://doi.acm.org/10.1145/1328438.1328464}, + doi = {10.1145/1328438.1328464}, + acmid = {1328464}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {CFL reachability, alias analysis, demand-driven analysis, memory disambiguation, pointer analysis} +} + +@inproceedings{Nole:2016:RPQ:2949689.2949711, + author = {Nol{\'e}, Maurizio and Sartiani, Carlo}, + title = {Regular Path Queries on Massive Graphs}, + booktitle = {Proceedings of the 28th International Conference on Scientific and Statistical Database Management}, + series = {SSDBM '16}, + year = {2016}, + isbn = {978-1-4503-4215-5}, + location = {Budapest, Hungary}, + pages = {13:1--13:12}, + articleno = {13}, + numpages = {12}, + url = {http://doi.acm.org/10.1145/2949689.2949711}, + doi = {10.1145/2949689.2949711}, + acmid = {2949711}, + publisher = {ACM}, + address = {New York, NY, USA} +} + +@article{DBLP:journals/corr/abs-1010-5023, + author = {Matthew Might and + David Darais}, + title = {Yacc is dead}, + journal = {CoRR}, + volume = {abs/1010.5023}, + year = {2010}, + url = {http://arxiv.org/abs/1010.5023}, + archiveprefix = {arXiv}, + eprint = {1010.5023}, + timestamp = {Mon, 13 Aug 2018 16:46:08 +0200}, + biburl = {https://dblp.org/rec/bib/journals/corr/abs-1010-5023}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@inproceedings{Adams:2016:CPP:2908080.2908128, + author = {Adams, Michael D. and Hollenbeck, Celeste and Might, Matthew}, + title = {On the Complexity and Performance of Parsing with Derivatives}, + booktitle = {Proceedings of the 37th ACM SIGPLAN Conference on Programming Language Design and Implementation}, + series = {PLDI '16}, + year = {2016}, + isbn = {978-1-4503-4261-2}, + location = {Santa Barbara, CA, USA}, + pages = {224--236}, + numpages = {13}, + url = {http://doi.acm.org/10.1145/2908080.2908128}, + doi = {10.1145/2908080.2908128}, + acmid = {2908128}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {Parsing, Parsing with derivatives, Performance} +} + +@article{Might:2011:PDF:2034574.2034801, + author = {Might, Matthew and Darais, David and Spiewak, Daniel}, + title = {Parsing with Derivatives: A Functional Pearl}, + journal = {SIGPLAN Not.}, + issue_date = {September 2011}, + volume = {46}, + number = {9}, + month = sep, + year = {2011}, + issn = {0362-1340}, + pages = {189--195}, + numpages = {7}, + url = {http://doi.acm.org/10.1145/2034574.2034801}, + doi = {10.1145/2034574.2034801}, + acmid = {2034801}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {context-free grammar, derivative, formal languages, parser combinator, parsing, regular expressions} +} + +@article{andersenparsing, + title = {Parsing With Derivatives}, + author = {Andersen, Leif} +} + +@phdthesis{SPPF, + title = {Parser generation for interactive environments}, + author = {Rekers, Joan Gerard}, + year = {1992}, + school = {Universiteit van Amsterdam} +} + +@article{Scott:2006:RNG:1146809.1146810, + author = {Scott, Elizabeth and Johnstone, Adrian}, + title = {Right Nulled GLR Parsers}, + journal = {ACM Trans. Program. Lang. Syst.}, + issue_date = {July 2006}, + volume = {28}, + number = {4}, + month = jul, + year = {2006}, + issn = {0164-0925}, + pages = {577--618}, + numpages = {42}, + url = {http://doi.acm.org/10.1145/1146809.1146810}, + doi = {10.1145/1146809.1146810}, + acmid = {1146810}, + publisher = {ACM}, + address = {New York, NY, USA}, + keywords = {General context-free grammars, generalized LR parsing} +} + +@inproceedings{10.1007/978-3-662-46663-6_5, + author = {Afroozeh, Ali + and Izmaylova, Anastasia}, + editor = {Franke, Bj{\"o}rn}, + title = {Faster, Practical GLL Parsing}, + booktitle = {Compiler Construction}, + year = {2015}, + publisher = {Springer Berlin Heidelberg}, + address = {Berlin, Heidelberg}, + pages = {89--108}, + abstract = {Generalized LL (GLL) parsing is an extension of recursivedescent (RD) parsing that supports all context-free grammars in cubic time and space. GLL parsers have the direct relationship with the grammar that RD parsers have, and therefore, compared to GLR, are easier to understand, debug, and extend. This makes GLL parsing attractive for parsing programming languages.}, + isbn = {978-3-662-46663-6} +} + +@article{Scott:2007:BCT:1289813.1289815, + author = {Scott, Elizabeth and Johnstone, Adrian and Economopoulos, Rob}, + title = {BRNGLR: A Cubic Tomita-style GLR Parsing Algorithm}, + journal = {Acta Inf.}, + issue_date = {September 2007}, + volume = {44}, + number = {6}, + month = sep, + year = {2007}, + issn = {0001-5903}, + pages = {427--461}, + numpages = {35}, + url = {http://dx.doi.org/10.1007/s00236-007-0054-z}, + doi = {10.1007/s00236-007-0054-z}, + acmid = {1289815}, + publisher = {Springer-Verlag New York, Inc.}, + address = {Secaucus, NJ, USA} +} + +@inproceedings{Billot:1989:SSF:981623.981641, + author = {Billot, Sylvie and Lang, Bernard}, + title = {The Structure of Shared Forests in Ambiguous Parsing}, + booktitle = {Proceedings of the 27th Annual Meeting on Association for Computational Linguistics}, + series = {ACL '89}, + year = {1989}, + location = {Vancouver, British Columbia, Canada}, + pages = {143--151}, + numpages = {9}, + url = {https://doi.org/10.3115/981623.981641}, + doi = {10.3115/981623.981641}, + acmid = {981641}, + publisher = {Association for Computational Linguistics}, + address = {Stroudsburg, PA, USA}, + keywords = {Ambiguity, Chart Parsing, Context-Free Parsing, Dynamic Programming, Earley Parsing, Parse Forest, Parse Tree, Parsing Schemata, Parsing Strategies} +} + +@article{Scott:2010:GP:1860132.1860320, + author = {Scott, Elizabeth and Johnstone, Adrian}, + title = {GLL Parsing}, + journal = {Electron. Notes Theor. Comput. Sci.}, + issue_date = {September, 2010}, + volume = {253}, + number = {7}, + month = sep, + year = {2010}, + issn = {1571-0661}, + pages = {177--189}, + numpages = {13}, + url = {http://dx.doi.org/10.1016/j.entcs.2010.08.041}, + doi = {10.1016/j.entcs.2010.08.041}, + acmid = {1860320}, + publisher = {Elsevier Science Publishers B. V.}, + address = {Amsterdam, The Netherlands, The Netherlands}, + keywords = {RNGLR and RIGLR parsing, context free languages, generalised parsing, recursive descent} +} + +@article{Okhotin:2014:PMM:2565359.2565379, + author = {Okhotin, Alexander}, + title = {Parsing by Matrix Multiplication Generalized to Boolean Grammars}, + journal = {Theor. Comput. Sci.}, + issue_date = {January, 2014}, + volume = {516}, + month = jan, + year = {2014}, + issn = {0304-3975}, + pages = {101--120}, + numpages = {20}, + url = {http://dx.doi.org/10.1016/j.tcs.2013.09.011}, + doi = {10.1016/j.tcs.2013.09.011}, + acmid = {2565379}, + publisher = {Elsevier Science Publishers Ltd.}, + address = {Essex, UK}, + keywords = {Boolean grammars, Conjunctive grammars, Context-free grammars, Matrix multiplication, Parsing} +} + +@inproceedings{Okhotin:2003:BG:1758089.1758123, + author = {Okhotin, Alexander}, + title = {Boolean Grammars}, + booktitle = {Proceedings of the 7th International Conference on Developments in Language Theory}, + series = {DLT'03}, + year = {2003}, + isbn = {3-540-40434-1}, + location = {Szeged, Hungary}, + pages = {398--410}, + numpages = {13}, + url = {http://dl.acm.org/citation.cfm?id=1758089.1758123}, + acmid = {1758123}, + publisher = {Springer-Verlag}, + address = {Berlin, Heidelberg} +} + +@article{OKHOTIN2014101, + title = {Parsing by matrix multiplication generalized to Boolean grammars}, + journal = {Theoretical Computer Science}, + volume = {516}, + pages = {101 - 120}, + year = {2014}, + issn = {0304-3975}, + doi = {https://doi.org/10.1016/j.tcs.2013.09.011}, + url = {http://www.sciencedirect.com/science/article/pii/S0304397513006919}, + author = {Alexander Okhotin}, + keywords = {Boolean grammars, Conjunctive grammars, Context-free grammars, Matrix multiplication, Parsing}, + abstract = {The well-known parsing algorithm for context-free grammars due to Valiant (1975) [25] is analyzed and extended to handle the more general Boolean grammars, which are context-free grammars augmented with conjunction and negation operators in the rules. The algorithm reduces construction of a parsing table to computing multiple products of Boolean matrices of various sizes. Its time complexity on an input string of length n is O(BMM(n)logn), where BMM(n) is the number of operations needed to multiply two Boolean matrices of size n×n, which is O(nω) with ω<2.373 as per the current knowledge. A parse tree can be constructed in time MM(n)logO(1)n (where MM(n) is the complexity of multiplying two integer matrices), by applying a known efficient procedure for determining witnesses for Boolean matrix multiplication. The algorithm has a succinct proof of correctness and is ready to be implemented.} +} + +@article{f60a33d409364914be560cac0e54b12c, + title = {Conjunctive and boolean grammars: The true general case of the context-free grammars}, + abstract = {Conjunctive grammars extend the definition of a context-free grammar by allowing a conjunction operation in the rules; Boolean grammars are further equipped with an explicit negation. These grammars maintain the main principle of the context-free grammars, that of defining syntactically correct strings inductively from their substrings, but lift the restriction of using disjunction only. This paper surveys the results on conjunctive and Boolean grammars obtained over the last decade, comparing them to the corresponding results for ordinary context-free grammars and their main subfamilies. Much attention is given to parsing algorithms, most of which are inherited from the case of ordinary context-free grammars without increasing their computational complexity. The intended readership includes any computer scientists looking for a compact and accessible description of this formal model and its properties, as well as for a general outlook on formal grammars. The paper is also addressed to theoretical computer scientists seeking a subject for research; an account of pure theoretical research in the area presented in this paper is accompanied by a list of significant open problems, with an award offered for the first correct solution of each problem. Several directions for future investigation are proposed.}, + keywords = {Boolean grammars, Conjunctive grammars, Context-free grammars, Formal languages, Language equations, Parsing}, + author = {Alexander Okhotin}, + year = {2013}, + month = {8}, + day = {1}, + doi = {10.1016/j.cosrev.2013.06.001}, + language = {English}, + volume = {9}, + pages = {27--59}, + journal = {Computer Science Review}, + issn = {1574-0137}, + publisher = {Elsevier} +} + +@article{565CECD7E8F5C6063935B41DB41797AA37D53B04, + author = {Azimov, Rustam and Grigorev, Semyon}, + year = {2018}, + month = {01}, + pages = {149-166}, + title = {Path querying using conjunctive grammars}, + volume = {30}, + journal = {Proceedings of the Institute for System Programming of the RAS}, + doi = {10.15514/ISPRAS-2018-30(2)-8} +} + +@inproceedings{10.1007/978-3-319-46523-4_38, + author = {Zhang, Xiaowang + and Feng, Zhiyong + and Wang, Xin + and Rao, Guozheng + and Wu, Wenrui}, + editor = {Groth, Paul + and Simperl, Elena + and Gray, Alasdair + and Sabou, Marta + and Kr{\"o}tzsch, Markus + and Lecue, Freddy + and Fl{\"o}ck, Fabian + and Gil, Yolanda}, + title = {Context-Free Path Queries on RDF Graphs}, + booktitle = {The Semantic Web -- ISWC 2016}, + year = {2016}, + publisher = {Springer International Publishing}, + address = {Cham}, + pages = {632--648}, + abstract = {Navigational graph queries are an important class of queries that can extract implicit binary relations over the nodes of input graphs. Most of the navigational query languages used in the RDF community, e.g. property paths in W3C SPARQL 1.1 and nested regular expressions in nSPARQL, are based on the regular expressions. It is known that regular expressions have limited expressivity; for instance, some natural queries, like same generation-queries, are not expressible with regular expressions. To overcome this limitation, in this paper, we present cfSPARQL, an extension of SPARQL query language equipped with context-free grammars. The cfSPARQL language is strictly more expressive than property paths and nested expressions. The additional expressivity can be used for modelling graph similarities, graph summarization and ontology alignment. Despite the increasing expressivity, we show that cfSPARQL still enjoys a low computational complexity and can be evaluated efficiently.}, + isbn = {978-3-319-46523-4} +} + +@inproceedings{hellingsRelational, + title = {Conjunctive context-free path queries}, + author = {Hellings, Jelle}, + booktitle = {Proceedings of ICDT'14}, + pages = {119--130}, + year = {2014} +} + +@misc{hellings2015querying, + title = {Querying for Paths in Graphs using Context-Free Path Queries}, + author = {Jelle Hellings}, + year = {2015}, + eprint = {1502.02242}, + archiveprefix = {arXiv}, + primaryclass = {cs.DB} +} + +@article{Hellings2015PathRF, + title = {Path Results for Context-free Grammar Queries on Graphs}, + author = {Jelle Hellings}, + journal = {ArXiv}, + year = {2015}, + volume = {abs/1502.02242} +} + +@inproceedings{bradford2007quickest, + title = {Quickest path distances on context-free labeled graphs}, + author = {Bradford, Phillip G}, + booktitle = {Appear in 6-th WSEAS Conference on Computational Intelligence, Man-Machine Systems and Cybernetics}, + year = {2007}, + organization = {Citeseer} +} + +@inproceedings{ward2008distributed, + title = {A distributed context-free language constrained shortest path algorithm}, + author = {Ward, Charles B and Wiegand, Nathan M and Bradford, Phillip G}, + booktitle = {2008 37th International Conference on Parallel Processing}, + pages = {373--380}, + year = {2008}, + organization = {IEEE} +} + +@inproceedings{bradford2016fast, + title = {Fast point-to-point Dyck constrained shortest paths on a DAG}, + author = {Bradford, Phillip G and Choppella, Venkatesh}, + booktitle = {2016 IEEE 7th Annual Ubiquitous Computing, Electronics \& Mobile Communication Conference (UEMCON)}, + pages = {1--7}, + year = {2016}, + organization = {IEEE} +} + +@inproceedings{Bradford:2008:LCG:1373936.1373946, + author = {Bradford, Phillip G.}, + title = {Language Constrained Graph Problems: A Microcosm of Engineering Research and Development}, + booktitle = {Proceedings of the 2Nd WSEAS International Conference on Computer Engineering and Applications}, + series = {CEA'08}, + year = {2008}, + isbn = {978-960-6766-33-6}, + location = {Acapulco, Mexico}, + pages = {71--76}, + numpages = {6}, + url = {http://dl.acm.org/citation.cfm?id=1373936.1373946}, + acmid = {1373946}, + publisher = {World Scientific and Engineering Academy and Society (WSEAS)}, + address = {Stevens Point, Wisconsin, USA}, + keywords = {creative destruction, entrepreneurship, integrated learning base, intellectual infrastructure, labeled graphs, paradigm shift, path problems, science and business} +} + + +@article{doi:10.1137/S0097539798337716, + author = {Barrett, C. and Jacob, R. and Marathe, M.}, + title = {Formal-Language-Constrained Path Problems}, + journal = {SIAM Journal on Computing}, + volume = {30}, + number = {3}, + pages = {809-837}, + year = {2000}, + doi = {10.1137/S0097539798337716}, + url = {https://doi.org/10.1137/S0097539798337716}, + eprint = { https://doi.org/10.1137/S0097539798337716} +} + +@article{barrett2007label, + title = {Label constrained shortest path algorithms: An experimental evaluation using transportation networks}, + author = {Barrett, Chris and Bisset, Keith and Holzer, Martin and Konjevod, Goran and Marathe, Madhav and Wagner, Dorothea}, + journal = {March}, + volume = {9}, + pages = {2007}, + year = {2007} +} + +@article{Ward:2010:CRL:1710158.1710234, + author = {Ward, Charles B. and Wiegand, Nathan M.}, + title = {Complexity Results on Labeled Shortest Path Problems from Wireless Routing Metrics}, + journal = {Comput. Netw.}, + issue_date = {February, 2010}, + volume = {54}, + number = {2}, + month = feb, + year = {2010}, + issn = {1389-1286}, + pages = {208--217}, + numpages = {10}, + url = {http://dx.doi.org/10.1016/j.comnet.2009.04.012}, + doi = {10.1016/j.comnet.2009.04.012}, + acmid = {1710234}, + publisher = {Elsevier North-Holland, Inc.}, + address = {New York, NY, USA}, + keywords = {Approximation algorithms, Labeled paths, Shortest paths, Wireless routing metrics} +} + +@inproceedings{kupferman2016eulerian, + title = {Eulerian paths with regular constraints}, + author = {Kupferman, Orna and Vardi, Gal}, + booktitle = {41st International Symposium on Mathematical Foundations of Computer Science (MFCS 2016)}, + year = {2016}, + organization = {Schloss Dagstuhl-Leibniz-Zentrum fuer Informatik} +} + +@inproceedings{10.1007/978-3-642-22321-1_24, + author = {Holzer, Markus + and Kutrib, Martin + and Leiter, Ursula}, + editor = {Mauri, Giancarlo + and Leporati, Alberto}, + title = {Nodes Connected by Path Languages}, + booktitle = {Developments in Language Theory}, + year = {2011}, + publisher = {Springer Berlin Heidelberg}, + address = {Berlin, Heidelberg}, + pages = {276--287}, + abstract = {We investigate reachability problems on different types of labeled graphs constrained to formal languages from a family {\$}{\backslash}mathcal{\{}L{\}}{\$}. If every language in {\$}{\backslash}mathcal{\{}L{\}}{\$}is accepted by a one-way nondeterministic storage automaton, then we give an appealing characterization of the computational complexity of the labeled graph reachability problem in terms of two-way nondeterministic storage automata with auxiliary worktape that is logarithmic-space bounded. Moreover, we also consider acyclic graphs in the underlying reachability instance, obtaining a lower bound result for auxiliary storage automata that are simultaneously space and time restricted.}, + isbn = {978-3-642-22321-1} +} + +@inproceedings{axelsson2011formal, + title = {Formal language constrained reachability and model checking propositional dynamic logics}, + author = {Axelsson, Roland and Lange, Martin}, + booktitle = {International Workshop on Reachability Problems}, + pages = {45--57}, + year = {2011}, + organization = {Springer} +} + +@phdthesis{DBLP:phd/ethos/Economopoulos06, + author = {Giorgios Rob Economopoulos}, + title = {Generalised {LR} parsing algorithms}, + school = {Royal Holloway, University of London, {UK}}, + year = {2006}, + url = {http://ethos.bl.uk/OrderDetails.do?uin=uk.bl.ethos.435358}, + timestamp = {Mon, 05 Sep 2016 19:00:20 +0200}, + biburl = {https://dblp.org/rec/bib/phd/ethos/Economopoulos06}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@article{DBLP:journals/jalc/Okhotin01, + author = {Alexander Okhotin}, + title = {Conjunctive Grammars}, + journal = {Journal of Automata, Languages and Combinatorics}, + volume = {6}, + number = {4}, + pages = {519--535}, + year = {2001}, + url = {https://doi.org/10.25596/jalc-2001-519}, + doi = {10.25596/jalc-2001-519}, + timestamp = {Thu, 15 Nov 2018 14:56:53 +0100}, + biburl = {https://dblp.org/rec/bib/journals/jalc/Okhotin01}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@article{Okhotin2002, + author = {Okhotin, A. S.}, + title = {Conjunctive Grammars and Systems of Language Equations}, + journal = {Programming and Computer Software}, + year = {2002}, + month = {Sep}, + day = {01}, + volume = {28}, + number = {5}, + pages = {243--249}, + abstract = {This paper studies systems of language equations that are resolved with respect to variables and contain the operations of concatenation, union and intersection. Every system of this kind is proved to have a least fixed point, and the equivalence of these systems to conjunctive grammars is established. This allows us to obtain an algebraic characterization of the language family generated by conjunctive grammars.}, + issn = {1608-3261}, + doi = {10.1023/A:1020213411126}, + url = {https://doi.org/10.1023/A:1020213411126} +} + + +@article{DBLP:journals/tcs/Okhotin03a, + author = {Alexander Okhotin}, + title = {On the closure properties of linear conjunctive languages}, + journal = {Theor. Comput. Sci.}, + volume = {299}, + number = {1-3}, + pages = {663--685}, + year = {2003}, + url = {https://doi.org/10.1016/S0304-3975(02)00543-1}, + doi = {10.1016/S0304-3975(02)00543-1}, + timestamp = {Wed, 14 Jun 2017 20:32:07 +0200}, + biburl = {https://dblp.org/rec/bib/journals/tcs/Okhotin03a}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@article{SEKI1991191, + title = {On multiple context-free grammars}, + journal = {Theoretical Computer Science}, + volume = {88}, + number = {2}, + pages = {191 - 229}, + year = {1991}, + issn = {0304-3975}, + doi = {https://doi.org/10.1016/0304-3975(91)90374-B}, + url = {http://www.sciencedirect.com/science/article/pii/030439759190374B}, + author = {Hiroyuki Seki and Takashi Matsumura and Mamoru Fujii and Tadao Kasami}, + abstract = {Multiple context-free grammars (mcfg's) is a subclass of generalized context-free grammars introduced by Pollard (1984) in order to describe the syntax of natural languages. The class of languages generated by mcfg's (called multiple context-free languages or, shortly, mcfl's) properly includes the class of context-free languages and is properly included in the class of context-sensitive languages. First, the paper presents results on the generative capacity of mcfg's and also on the properties of mcfl's such as formal language-theoretic closure properties. Next, it is shown that the time complexity of the membership problem for multiple context-free languages is O(ne), where n is the length of an input string and e is a constant called the degree of a given mcfg. Head grammars (hg's) introduced by Pollard and tree adjoining grammars (tag's) introduced by Joshi et al. (1975) are also grammatical formalisms to describe the syntax of natural languages. The paper also presents the following results on the generative capacities of hg's, tag's and 2-mcfg's, which are a subclass of mcfg's: (1) The class HL of languages generated by hg's is the same as the one generated by tag's; (2) HL is the same as the one generated by left-wrapping hg's (or right-wrapping hg's) which is a proper subclass of hg's; (3) HL is properly included in the one generated by 2-mcfg's. As a corollary of (1), it is also shown that HL is a substitution-closed full AFL.} +} + +@inbook{Joshi1997, + author = {Joshi, Aravind K. + and Schabes, Yves}, + editor = {Rozenberg, Grzegorz + and Salomaa, Arto}, + title = {Tree-Adjoining Grammars}, + booktitle = {Handbook of Formal Languages: Volume 3 Beyond Words}, + year = {1997}, + publisher = {Springer Berlin Heidelberg}, + address = {Berlin, Heidelberg}, + pages = {69--123}, + abstract = {In this paper, we will describe a tree generating system called tree-adjoining grammar (TAG) and state some of the recent results about TAGs. The work on TAGs is motivated by linguistic considerations. However, a number of formal results have been established for TAGs, which we believe, would be of interest to researchers in formal languages and automata, including those interested in tree grammars and tree automata.}, + isbn = {978-3-642-59126-6}, + doi = {10.1007/978-3-642-59126-6_2}, + url = {https://doi.org/10.1007/978-3-642-59126-6_2} +} + +@article{cfpqBio, + author = {Sevon, Petteri and Eronen, Lauri}, + year = {2008}, + month = {06}, + pages = {}, + title = {Subgraph Queries by Context-free Grammars}, + volume = {5}, + journal = {Journal of Integrative Bioinformatics}, + doi = {10.1515/jib-2008-100} +} + +@article{Floyd1962, + title = {Algorithm 97: shortest path}, + author = {Floyd, Robert W}, + journal = {Communications of the ACM}, + volume = {5}, + number = {6}, + pages = {345}, + year = {1962}, + publisher = {ACM} +} + +@article{Bernard1959, + title = {Transitivit{\'e} et connexit{\'e}}, + author = {Roy, Bernard}, + journal = {Comptes Rendus Hebdomadaires Des Seances De L Academie Des Sciences}, + volume = {249}, + number = {2}, + pages = {216--218}, + year = {1959}, + publisher = {GAUTHIER-VILLARS/EDITIONS ELSEVIER 23 RUE LINOIS, 75015 PARIS, FRANCE} +} + +@article{Warshall1962, + title = {A theorem on boolean matrices}, + author = {Warshall, Stephen}, + booktitle = {Journal of the ACM}, + year = {1962}, + organization = {Citeseer} +} + +@article{FredmanAPSP1976, + title = {New bounds on the complexity of the shortest path problem}, + author = {Fredman, Michael L}, + journal = {SIAM Journal on Computing}, + volume = {5}, + number = {1}, + pages = {83--89}, + year = {1976}, + publisher = {SIAM} +} + +@article{Dobosiewicz1990, + title = {A more efficient algorithm for the min-plus multiplication}, + author = {Dobosiewicz, Wlodzimierz}, + journal = {International journal of computer mathematics}, + volume = {32}, + number = {1-2}, + pages = {49--60}, + year = {1990}, + publisher = {Taylor \& Francis} +} + +@article{Takaoka1992, + title = {A new upper bound on the complexity of the all pairs shortest path problem}, + author = {Takaoka, Tadao}, + journal = {Information Processing Letters}, + volume = {43}, + number = {4}, + pages = {195--199}, + year = {1992}, + publisher = {Elsevier} +} + +@inproceedings{Takaoka2004, + author = {Takaoka, T.}, + title = {A faster algorithm for the all-pairs shortest path problem and its application}, + booktitle = {Computing and Combinatorics}, + booktitleaddon = {10th international conference}, + year = {2004}, + volume = {3106}, + pages = {278--289} +} + +@article{Takaoka2005, + author = {Takaoka, T.}, + title = {An $O(n^3 \log \log n/ \log n)$ time algorithm for the all-pairs shortest path problem}, + year = {2005}, + journal = {Information Processing Letters}, + volume = {96}, + pages = {155--161} +} + +@article{Han2004, + title = {Improved algorithm for all pairs shortest paths}, + author = {Han, Yijie}, + journal = {Information Processing Letters}, + volume = {91}, + number = {5}, + pages = {245--250}, + year = {2004}, + publisher = {Elsevier} +} + +@inproceedings{Zwick2004, + title = {A slightly improved sub-cubic algorithm for the all pairs shortest paths problem with real edge lengths}, + author = {Zwick, Uri}, + booktitle = {International Symposium on Algorithms and Computation}, + pages = {921--932}, + year = {2004}, + organization = {Springer} +} + +@inproceedings{Lavallee2004, + title = {An Efficient APSP Algorithm.}, + author = {Lavall{\'e}e, Ivan and Bui, Marc and Quoc, Trung Ha}, + booktitle = {RIVF}, + pages = {211--214}, + year = {2004} +} + +@article{Seidel1995, + title = {On the all-pairs-shortest-path problem in unweighted undirected graphs}, + author = {Seidel, Raimund}, + journal = {Journal of computer and system sciences}, + volume = {51}, + number = {3}, + pages = {400--403}, + year = {1995}, + publisher = {Elsevier} +} + +@article{Strassen1969, + title = {Gaussian elimination is not optimal}, + author = {Strassen, Volker}, + journal = {Numerische mathematik}, + volume = {13}, + number = {4}, + pages = {354--356}, + year = {1969}, + publisher = {Springer} +} + +@inproceedings{Pan1978, + title = {Strassen's algorithm is not optimal trilinear technique of aggregating, uniting and canceling for constructing fast algorithms for matrix operations}, + author = {Pan, V. Ya.}, + booktitle = {19th Annual Symposium on Foundations of Computer Science (sfcs 1978)}, + pages = {166--176}, + year = {1978}, + organization = {IEEE} +} +} + +@article{BiniCapoRoma1979, + author = {Bini, Dario Andrea and Capovani, Milvio and Romani, Francesco and Lotti, Grazia}, + title = {$O(n^{2.7799})$ complexity for approximate matrix multiplication}, + year = {1979}, + journal = {Information Processing Letters}, + volume = {8(5)}, + pages = {234--235} +} + +@article{Schonhage1981, + title = {Partial and total matrix multiplication}, + author = {Sch{\"o}nhage, Arnold}, + journal = {SIAM Journal on Computing}, + volume = {10}, + number = {3}, + pages = {434--455}, + year = {1981}, + publisher = {SIAM} +} + +@article{CoppWino1982, + title = {On the asymptotic complexity of matrix multiplication}, + author = {Coppersmith, Don and Winograd, Shmuel}, + journal = {SIAM Journal on Computing}, + volume = {11}, + number = {3}, + pages = {472--492}, + year = {1982}, + publisher = {SIAM} +} + +@article{CoppWino1990, + title = {Matrix multiplication via arithmetic progressions}, + author = {Coppersmith, Don and Winograd, Shmuel}, + journal = {Journal of symbolic computation}, + volume = {9}, + number = {3}, + pages = {251--280}, + year = {1990}, + publisher = {Academic Press} +} + +@article{Chan2010, + title = {More algorithms for all-pairs shortest paths in weighted graphs}, + author = {Chan, Timothy M}, + journal = {SIAM Journal on Computing}, + volume = {39}, + number = {5}, + pages = {2075--2089}, + year = {2010}, + publisher = {SIAM} +} + +@article{Wirth1977, + title = {What can we do about the unnecessary diversity of notation for syntactic definitions?}, + author = {Wirth, Niklaus}, + journal = {Communications of the ACM}, + volume = {20}, + number = {11}, + pages = {822--823}, + year = {1977}, + publisher = {ACM} +} + +@article{Hemerik2009, + title = {Towards a Taxonomy for ECFG and RRPG Parsing}, + author = {Hemerik, Kees}, + journal = {Proceedings of the 3rd International Conference on Language and Automata Theory and Applications}, + pages = {410--421}, + year = {2009}, + publisher = {LATA} +} +@inproceedings{tomita1988graph, + title = {Graph-structured Stack and Natural Language Parsing}, + author = {Tomita, Masaru}, + booktitle = {26th Annual Meeting of the Association for Computational Linguistics}, + month = jun, + year = {1988}, + address = {Buffalo, New York, USA}, + publisher = {Association for Computational Linguistics}, + url = {https://www.aclweb.org/anthology/P88-1031}, + doi = {10.3115/982023.982054}, + pages = {249--257} +} + +@article{tomita-1987-efficient, + title = {An Efficient Augmented-Context-Free Parsing Algorithm}, + author = {Tomita, Masaru}, + journal = {Computational Linguistics}, + volume = {13}, + year = {1987}, + url = {https://www.aclweb.org/anthology/J87-1004}, + pages = {31--46} +} + +@article{Brzozowski1964, + title = {Derivatives of Regular Expressions}, + author = {Brzozowski, Janusz A.}, + journal = {Journal of the ACM}, + volume = {11 (4)}, + year = {1964}, + pages = {481–-494}, + doi = {10.1145/321239.321249} +} + +@online{Earley, + author = {{Sylvain Salvati}}, + title = {Multiple Context-free Grammars}, + url = {https://www.labri.fr/perso/salvati/downloads/cours/esslli/course2.pdf}, + organization = {NRIA Bordeaux Sud-Ouest}, + date = {2016-02-02}, + urldate = {2019-12-25} +} + +@article{Datalog, + author = {G. Gottlob and S. Ceri and L. Tanca}, + journal = {IEEE Transactions on Knowledge \& Data Engineering}, + title = {What You Always Wanted to Know About Datalog (And Never Dared to Ask)}, + year = {1989}, + volume = {1}, + number = {01}, + issn = {1558-2191}, + pages = {146-166}, + keywords = {optimisation methods; datalog; database query language; logic programming; syntax; semantics; relational database; logic programming; query languages; relational databases}, + doi = {10.1109/69.43410}, + publisher = {IEEE Computer Society}, + address = {Los Alamitos, CA, USA}, + month = {jan} +} + +@inproceedings{Magic, + author = {Bancilhon, Francois and Maier, David and Sagiv, Yehoshua and Ullman, Jeffrey D}, + title = {Magic Sets and Other Strange Ways to Implement Logic Programs (Extended Abstract)}, + booktitle = {Proceedings of the Fifth ACM SIGACT-SIGMOD Symposium on Principles of Database Systems}, + series = {PODS '86}, + year = {1986}, + isbn = {0-89791-179-2}, + location = {Cambridge, Massachusetts, USA}, + pages = {1--15}, + numpages = {15}, + url = {http://doi.acm.org/10.1145/6012.15399}, + doi = {10.1145/6012.15399}, + acmid = {15399}, + publisher = {ACM}, + address = {New York, NY, USA} +} + +@article{Dyrka2019, + doi = {10.7717/peerj.6559}, + url = {https://doi.org/10.7717/peerj.6559}, + year = {2019}, + month = mar, + publisher = {{PeerJ}}, + volume = {7}, + pages = {e6559}, + author = {Witold Dyrka and Mateusz Pyzik and Fran{\c{c}}ois Coste and Hugo Talibart}, + title = {Estimating probabilistic context-free grammars for proteins using contact map constraints}, + journal = {{PeerJ}} +} +@article{WJAnderson2012, + doi = {10.1186/1471-2105-13-78}, + url = {https://doi.org/10.1186/1471-2105-13-78}, + year = {2012}, + publisher = {Springer Science and Business Media {LLC}}, + volume = {13}, + number = {1}, + pages = {78}, + author = {James WJ Anderson and Paula Tataru and Joe Staines and Jotun Hein and Rune Lyngs{\o}}, + title = {Evolving stochastic context--free grammars for {RNA} secondary structure prediction}, + journal = {{BMC} Bioinformatics} +} + +@article{zier2013rna, + title = {RNA pseudoknot prediction through stochastic conjunctive grammars}, + author = {Zier-Vogel, Ryan and Domaratzki, Michael}, + journal = {Computability in Europe 2013. Informal Proceedings}, + pages = {80--89}, + year = {2013} +} + +@inproceedings{10.5555/3305381.3305582, + author = {Kusner, Matt J. and Paige, Brooks and Hern\'{a}ndez-Lobato, Jos\'{e} Miguel}, + title = {Grammar Variational Autoencoder}, + year = {2017}, + publisher = {JMLR.org}, + booktitle = {Proceedings of the 34th International Conference on Machine Learning - Volume 70}, + pages = {1945–1954}, + numpages = {10}, + location = {Sydney, NSW, Australia}, + series = {ICML’17} +} + +@inproceedings{kasai-etal-2017-tag, + title = {{TAG} Parsing with Neural Networks and Vector Representations of Supertags}, + author = {Kasai, Jungo and + Frank, Bob and + McCoy, Tom and + Rambow, Owen and + Nasr, Alexis}, + booktitle = {Proceedings of the 2017 Conference on Empirical Methods in Natural Language Processing}, + month = sep, + year = {2017}, + address = {Copenhagen, Denmark}, + publisher = {Association for Computational Linguistics}, + url = {https://www.aclweb.org/anthology/D17-1180}, + doi = {10.18653/v1/D17-1180}, + pages = {1712--1722}, + abstract = {We present supertagging-based models for Tree Adjoining Grammar parsing that use neural network architectures and dense vector representation of supertags (elementary trees) to achieve state-of-the-art performance in unlabeled and labeled attachment scores. The shift-reduce parsing model eschews lexical information entirely, and uses only the 1-best supertags to parse a sentence, providing further support for the claim that supertagging is {``}almost parsing.{''} We demonstrate that the embedding vector representations the parser induces for supertags possess linguistically interpretable structure, supporting analogies between grammatical structures like those familiar from recent work in distributional semantics. This dense representation of supertags overcomes the drawbacks for statistical models of TAG as compared to CCG parsing, raising the possibility that TAG is a viable alternative for NLP tasks that require the assignment of richer structural descriptions to sentences.} +} +@inproceedings{kasai-etal-2018-end, + title = {End-to-End Graph-Based {TAG} Parsing with Neural Networks}, + author = {Kasai, Jungo and + Frank, Robert and + Xu, Pauli and + Merrill, William and + Rambow, Owen}, + booktitle = {Proceedings of the 2018 Conference of the North {A}merican Chapter of the Association for Computational Linguistics: Human Language Technologies, Volume 1 (Long Papers)}, + month = jun, + year = {2018}, + address = {New Orleans, Louisiana}, + publisher = {Association for Computational Linguistics}, + url = {https://www.aclweb.org/anthology/N18-1107}, + doi = {10.18653/v1/N18-1107}, + pages = {1181--1194}, + abstract = {We present a graph-based Tree Adjoining Grammar (TAG) parser that uses BiLSTMs, highway connections, and character-level CNNs. Our best end-to-end parser, which jointly performs supertagging, POS tagging, and parsing, outperforms the previously reported best results by more than 2.2 LAS and UAS points. The graph-based parsing architecture allows for global inference and rich feature representations for TAG parsing, alleviating the fundamental trade-off between transition-based and graph-based parsing systems. We also demonstrate that the proposed parser achieves state-of-the-art performance in the downstream tasks of Parsing Evaluation using Textual Entailments (PETE) and Unbounded Dependency Recovery. This provides further support for the claim that TAG is a viable formalism for problems that require rich structural analysis of sentences.} +} + +@article{10.1145/373243.360208, + author = {Rehof, Jakob and F\"{a}hndrich, Manuel}, + title = {Type-Base Flow Analysis: From Polymorphic Subtyping to CFL-Reachability}, + year = {2001}, + issue_date = {March 2001}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {36}, + number = {3}, + issn = {0362-1340}, + url = {https://doi.org/10.1145/373243.360208}, + doi = {10.1145/373243.360208}, + journal = {SIGPLAN Not.}, + month = jan, + pages = {54--66}, + numpages = {13} +} + +@inproceedings{10.1145/193173.195287, + author = {Reps, Thomas and Horwitz, Susan and Sagiv, Mooly and Rosay, Genevieve}, + title = {Speeding up Slicing}, + year = {1994}, + isbn = {0897916913}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + url = {https://doi.org/10.1145/193173.195287}, + doi = {10.1145/193173.195287}, + booktitle = {Proceedings of the 2nd ACM SIGSOFT Symposium on Foundations of Software Engineering}, + pages = {11--20}, + numpages = {10}, + keywords = {flow-sensitive summary information, dynamic programming, program slicing, realizable path, program debugging, program dependence graph, dynamic transitive closure}, + location = {New Orleans, Louisiana, USA}, + series = {SIGSOFT '94} +} + +@inproceedings{10.1145/2001420.2001440, + author = {Yan, Dacong and Xu, Guoqing and Rountev, Atanas}, + title = {Demand-Driven Context-Sensitive Alias Analysis for Java}, + year = {2011}, + isbn = {9781450305624}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + url = {https://doi.org/10.1145/2001420.2001440}, + doi = {10.1145/2001420.2001440}, + booktitle = {Proceedings of the 2011 International Symposium on Software Testing and Analysis}, + pages = {155--165}, + numpages = {11}, + keywords = {demand-driven, alias analysis, context sensitivity}, + location = {Toronto, Ontario, Canada}, + series = {ISSTA '11} +} + +@article{10.1145/2714064.2660213, + author = {Zhang, Qirun and Xiao, Xiao and Zhang, Charles and Yuan, Hao and Su, Zhendong}, + title = {Efficient Subcubic Alias Analysis for C}, + year = {2014}, + issue_date = {December 2014}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {49}, + number = {10}, + issn = {0362-1340}, + url = {https://doi.org/10.1145/2714064.2660213}, + doi = {10.1145/2714064.2660213}, + journal = {SIGPLAN Not.}, + month = oct, + pages = {829--845}, + numpages = {17}, + keywords = {cfl-reachability, alias analysis} +} + +@article{Shemetova2019, + doi = {10.15514/ispras-2019-31(4)-14}, + url = {https://doi.org/10.15514/ispras-2019-31(4)-14}, + year = {2019}, + publisher = {Institute for System Programming of the Russian Academy of Sciences}, + volume = {31}, + number = {4}, + pages = {211--226}, + author = {E.N. Shemetova and S.V. Grigorev}, + title = {Path querying on acyclic graphs using Boolean grammars}, + journal = {Proceedings of the Institute for System Programming of {RAS}} +} + +@article{DBLP:journals/corr/abs-0811-1714, + author = {Martin R. Albrecht and + Gregory V. Bard and + William Hart}, + title = {Efficient Multiplication of Dense Matrices over {GF(2)}}, + journal = {CoRR}, + volume = {abs/0811.1714}, + year = {2008}, + url = {http://arxiv.org/abs/0811.1714}, + archiveprefix = {arXiv}, + eprint = {0811.1714}, + timestamp = {Mon, 13 Aug 2018 16:45:56 +0200}, + biburl = {https://dblp.org/rec/journals/corr/abs-0811-1714.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} + +@misc{Cusp, + author = {Steven Dalton and Nathan Bell and Luke Olson and Michael Garland}, + title = {Cusp: Generic Parallel Algorithms for Sparse Matrix and Graph Computations}, + year = {2014}, + url = {http://cusplibrary.github.io/}, + note = {Version 0.5.0} +} + +@inproceedings{Davis2018Algorithm9S, + title = {Algorithm 9xx: SuiteSparse:GraphBLAS: graph algorithms in the language of sparse linear algebra}, + author = {Timothy A. Davis}, + year = {2018} +} + +@inproceedings{10.1145/3357766.3359532, + author = {Scott, Elizabeth and Johnstone, Adrian}, + title = {Multiple Lexicalisation (a Java Based Study)}, + year = {2019}, + isbn = {9781450369817}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + url = {https://doi.org/10.1145/3357766.3359532}, + doi = {10.1145/3357766.3359532}, + booktitle = {Proceedings of the 12th ACM SIGPLAN International Conference on Software Language Engineering}, + pages = {71–82}, + numpages = {12}, + keywords = {syntax analysis, lexicalisation, generalised parsing}, + location = {Athens, Greece}, + series = {SLE 2019} +} + +@article{BEATTY1980193, + title = {Two iteration theorems for the LL(k) languages}, + journal = {Theoretical Computer Science}, + volume = {12}, + number = {2}, + pages = {193 - 228}, + year = {1980}, + issn = {0304-3975}, + doi = {https://doi.org/10.1016/0304-3975(80)90029-8}, + url = {http://www.sciencedirect.com/science/article/pii/0304397580900298}, + author = {John C. Beatty}, + abstract = {The structure of derivation trees over an LL(k) grammar is explored and a property of these trees obtained which is shown to characterize the LL(k) grammars. This characterization, called the LL(k) Left Part Theorem, makes it possible to establish a pair of iteration theorems for the LL(k) languages. These theorems provide a general and powerful method of showing that a language is not LL(k) when that is the case. They thus provide for the first time a flexible tool with which to explore the structure of the LL(k) languages and with which to discriminate between the LL(k) and LR(k) language classes. Examples are given of LR(k) languages which, for various reasons, fail to be LL(k). Easy and rigorous proofs to this effect are given using our LL(k) iteration theorems. In particular, it is proven that the dangling-ELSE construct allowed in PL/I and Pascal cannot be generated by any LL(k) grammar. We also give a new and straightforward proof based on the LL(k) Left Part Theorem that every LL(k) grammar is LR(k).} +} + +@misc{VavilovGroups, + language = {russian}, + author = {{\CYRN}иколай Вавилов}, + title = {КОНКРЕТНАЯ ТЕОРИЯ ГРУПП}, + year = {2005}, + url = {http://dobrochan.com/src/pdf/1512/Вавилов-Н.-Конкретная-теория-групп.-Основные-понят.pdf}, + note = {Дата доступа: 29 июня 2021 г.} +} + + +@misc{VavilovRings, + language = {russian}, + author = {{\CYRN}иколай Вавилов}, + title = {КОНКРЕТНАЯ ТЕОРИЯ КОЛЕЦ}, + year = {2006}, + url = {http://www.add3d.ru/wp-content/uploads/2019/10/Vavilov-Rings.pdf}, + note = {Дата доступа: 29 июня 2021 г.} +} + +@misc{das2018lower, + title = {Lower bounds for Combinatorial Algorithms for Boolean Matrix Multiplication}, + author = {Debarati Das and Michal Koucký and Michael Saks}, + year = {2018}, + eprint = {1801.05202}, + archiveprefix = {arXiv}, + primaryclass = {cs.CC} +} + +@misc{alman2020refined, + title = {A Refined Laser Method and Faster Matrix Multiplication}, + author = {Josh Alman and Virginia Vassilevska Williams}, + year = {2020}, + eprint = {2010.05846}, + archiveprefix = {arXiv}, + primaryclass = {cs.DS} +} + +@inproceedings{5438580, + author = {Bansal, Nikhil and Williams, Ryan}, + booktitle = {2009 50th Annual IEEE Symposium on Foundations of Computer Science}, + title = {Regularity Lemmas and Combinatorial Algorithms}, + year = {2009}, + volume = {}, + number = {}, + pages = {745-754}, + doi = {10.1109/FOCS.2009.76} +} + +@inproceedings{10.1007/978-3-662-47672-7_89, + author = {Yu, Huacheng}, + editor = {Halld{\'o}rsson, Magn{\'u}s M. + and Iwama, Kazuo + and Kobayashi, Naoki + and Speckmann, Bettina}, + title = {An Improved Combinatorial Algorithm for Boolean Matrix Multiplication}, + booktitle = {Automata, Languages, and Programming}, + year = {2015}, + publisher = {Springer Berlin Heidelberg}, + address = {Berlin, Heidelberg}, + pages = {1094--1105}, + abstract = {We present a new combinatorial algorithm for triangle finding and Boolean matrix multiplication that runs in {\$}{\$}{\backslash}hat{\{}O{\}}(n^3/{\backslash}log ^4 n){\$}{\$}O^(n3/log4n)time, where the {\$}{\$}{\backslash}hat{\{}O{\}}{\$}{\$}O^notation suppresses poly(loglog) factors. This improves the previous best combinatorial algorithm by Chan [4] that runs in {\$}{\$}{\backslash}hat{\{}O{\}}(n^3/{\backslash}log ^3 n){\$}{\$}O^(n3/log3n)time. Our algorithm generalizes the divide-and-conquer strategy of Chan's algorithm.}, + isbn = {978-3-662-47672-7} +} + + +@article{ArlDinKro70, + author = {{\CYRV}. Арлазаров and {\CYRE}. Диниц and {\CYRM}. Кронрод and {\CYRI}. Фараджев}, + title = {Об экономном построении транзитивного замыкания ориентированного графа}, + journal = {Докл. АН СССР}, + year = {1970}, + volume = {194}, + number = {3}, + pages = {487--488}, + url = {http://mi.mathnet.ru/dan35675} +} + +@book{doi:10.1137/1.9780898719918, + author = {Kepner, Jeremy and Gilbert, John}, + editor = {Jeremy Kepner and John Gilbert}, + title = {Graph Algorithms in the Language of Linear Algebra}, + publisher = {Society for Industrial and Applied Mathematics}, + year = {2011}, + doi = {10.1137/1.9780898719918}, + address = {}, + edition = {}, + url = {https://epubs.siam.org/doi/abs/10.1137/1.9780898719918}, + eprint = {https://epubs.siam.org/doi/pdf/10.1137/1.9780898719918} +} +@misc{tata2007, + author = {H. Comon and M. Dauchet and R. Gilleron and C. L\"oding + and F. Jacquemard + and D. Lugiez and S. Tison and M. Tommasi}, + title = {Tree Automata Techniques and Applications}, + howpublished = {Available on: \url{http://www.grappa.univ-lille3.fr/tata}}, + note = {release October, 12th 2007}, + year = 2007 +} + +@inproceedings{Baras2010PathPI, + title = {Path Problems in Networks}, + author = {J. Baras and George Theodorakopoulos}, + booktitle = {Path Problems in Networks}, + year = {2010} +} +@article{EHRIG1992557, + title = {Introduction to graph grammars with applications to semantic networks}, + journal = {Computers \& Mathematics with Applications}, + volume = {23}, + number = {6}, + pages = {557-572}, + year = {1992}, + issn = {0898-1221}, + doi = {https://doi.org/10.1016/0898-1221(92)90124-Z}, + url = {https://www.sciencedirect.com/science/article/pii/089812219290124Z}, + author = {Hartmut Ehrig and Annegret Habel and Hans-Jörg Kreowski}, + abstract = {In the first half of this paper, we give an introductory survey on graph grammars that provide rule-based mechanisms for generating, manipulating and analyzing graphs. In the second half, two potential applications of graph-grammar concepts to semantic networks are indicated.} +} + +@book{Courcelle2009, + doi = {10.1017/cbo9780511977619}, + url = {https://doi.org/10.1017/cbo9780511977619}, + year = {2009}, + publisher = {Cambridge University Press}, + author = {Bruno Courcelle and Joost Engelfriet}, + title = {Graph Structure and Monadic Second-Order Logic} +} + +@inproceedings{9286186, + author = {Elekes, Márton and Nagy, Attila and Sándor, Dávid and Antal, János Benjamin and Davis, Timothy A. and Szárnyas, Gábor}, + booktitle = {2020 IEEE High Performance Extreme Computing Conference (HPEC)}, + title = {A GraphBLAS solution to the SIGMOD 2014 Programming Contest using multi-source BFS}, + year = {2020}, + volume = {}, + number = {}, + pages = {1-7}, + doi = {10.1109/HPEC43674.2020.9286186} +} + +@inproceedings{10.1145/3315454.3329962, + author = {Spampinato, Daniele G. and Sridhar, Upasana and Low, Tze Meng}, + title = {Linear Algebraic Depth-First Search}, + year = {2019}, + isbn = {9781450367172}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + url = {https://doi.org/10.1145/3315454.3329962}, + doi = {10.1145/3315454.3329962}, + abstract = {There is a recent push by a segment of the graph community to implement graph algorithms in the language of linear algebra. However, graph algorithms that depend on depth-first search (DFS) techniques are often highlighted as limitations of the linear algebraic approach as linear algebraic formulation of DFS algorithms are few, if any. This paper provides a linear algebraic approach for developing DFS graph algorithms and demonstrates its use for defining three classical DFS-based computations: Binary tree traversal, topological sort, and biconnected components.}, + booktitle = {Proceedings of the 6th ACM SIGPLAN International Workshop on Libraries, Languages and Compilers for Array Programming}, + pages = {93–104}, + numpages = {12}, + keywords = {post-order traversal, pre-order traversal, topological sort, biconnected components, depth-first search, adjacency matrix, graph algorithms, linear algebra, permutations}, + location = {Phoenix, AZ, USA}, + series = {ARRAY 2019} +} + +@article{GEBHARDT202241, + title = {On is an n-MCFL}, + journal = {Journal of Computer and System Sciences}, + volume = {127}, + pages = {41-52}, + year = {2022}, + issn = {0022-0000}, + doi = {https://doi.org/10.1016/j.jcss.2022.02.003}, + url = {https://www.sciencedirect.com/science/article/pii/S0022000022000174}, + author = {Kilian Gebhardt and Frédéric Meunier and Sylvain Salvati}, + keywords = {Formal Languages, Multiple Context Free Languages, Commutative Languages, Tucker Lemma, Necklace splitting theorem, Word problem in groups}, + abstract = {Commutative properties in formal languages pose problems at the frontier of computer science, computational linguistics and computational group theory. A prominent problem of this kind is the position of the language On, the language that contains the same number of letters ai and a¯i with 1⩽i⩽n, in the known classes of formal languages. It has recently been shown that On is a Multiple Context-Free Language (MCFL). However the more precise conjecture of Nederhof that On is an MCFL of dimension n was left open. We prove this conjecture using tools from algebraic topology. On our way, we prove a variant of the necklace splitting theorem.} +} + +@article{salvati:inria-00564552, + title = {{MIX is a 2-MCFL and the word problem in $\mathbb{Z}^2$ is solved by a third-order collapsible pushdown automaton}}, + author = {Salvati, Sylvain}, + url = {https://inria.hal.science/inria-00564552}, + journal = {{Journal of Computer and System Sciences}}, + publisher = {{Elsevier}}, + volume = {81}, + number = {7}, + pages = {1252 - 1277}, + year = {2015}, + pdf = {https://inria.hal.science/inria-00564552/file/mix.pdf}, + hal_id = {inria-00564552}, + hal_version = {v1} +} + +@article{10.1145/3093333.3009848, + author = {Zhang, Qirun and Su, Zhendong}, + title = {Context-Sensitive Data-Dependence Analysis via Linear Conjunctive Language Reachability}, + year = {2017}, + issue_date = {January 2017}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {52}, + number = {1}, + issn = {0362-1340}, + url = {https://doi.org/10.1145/3093333.3009848}, + doi = {10.1145/3093333.3009848}, + abstract = {Many program analysis problems can be formulated as graph reachability problems. In the literature, context-free language (CFL) reachability has been the most popular formulation and can be computed in subcubic time. The context-sensitive data-dependence analysis is a fundamental abstraction that can express a broad range of program analysis problems. It essentially describes an interleaved matched-parenthesis language reachability problem. The language is not context-free, and the problem is well-known to be undecidable. In practice, many program analyses adopt CFL-reachability to exactly model the matched parentheses for either context-sensitivity or structure-transmitted data-dependence, but not both. Thus, the CFL-reachability formulation for context-sensitive data-dependence analysis is inherently an approximation. To support more precise and scalable analyses, this paper introduces linear conjunctive language (LCL) reachability, a new, expressive class of graph reachability. LCL not only contains the interleaved matched-parenthesis language, but is also closed under all set-theoretic operations. Given a graph with n nodes and m edges, we propose an O(mn) time approximation algorithm for solving all-pairs LCL-reachability, which is asymptotically better than known CFL-reachability algorithms. Our formulation and algorithm offer a new perspective on attacking the aforementioned undecidable problem - the LCL-reachability formulation is exact, while the LCL-reachability algorithm yields a sound approximation. We have applied the LCL-reachability framework to two existing client analyses. The experimental results show that the LCL-reachability framework is both more precise and scalable than the traditional CFL-reachability framework. This paper opens up the opportunity to exploit LCL-reachability in program analysis.}, + journal = {SIGPLAN Not.}, + month = {jan}, + pages = {344–358}, + numpages = {15}, + keywords = {program analysis, Context-free language reachability, linear conjunctive grammar, trellis automata} +} + +@inproceedings{10.1145/3009837.3009848, + author = {Zhang, Qirun and Su, Zhendong}, + title = {Context-Sensitive Data-Dependence Analysis via Linear Conjunctive Language Reachability}, + year = {2017}, + isbn = {9781450346603}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + url = {https://doi.org/10.1145/3009837.3009848}, + doi = {10.1145/3009837.3009848}, + abstract = {Many program analysis problems can be formulated as graph reachability problems. In the literature, context-free language (CFL) reachability has been the most popular formulation and can be computed in subcubic time. The context-sensitive data-dependence analysis is a fundamental abstraction that can express a broad range of program analysis problems. It essentially describes an interleaved matched-parenthesis language reachability problem. The language is not context-free, and the problem is well-known to be undecidable. In practice, many program analyses adopt CFL-reachability to exactly model the matched parentheses for either context-sensitivity or structure-transmitted data-dependence, but not both. Thus, the CFL-reachability formulation for context-sensitive data-dependence analysis is inherently an approximation. To support more precise and scalable analyses, this paper introduces linear conjunctive language (LCL) reachability, a new, expressive class of graph reachability. LCL not only contains the interleaved matched-parenthesis language, but is also closed under all set-theoretic operations. Given a graph with n nodes and m edges, we propose an O(mn) time approximation algorithm for solving all-pairs LCL-reachability, which is asymptotically better than known CFL-reachability algorithms. Our formulation and algorithm offer a new perspective on attacking the aforementioned undecidable problem - the LCL-reachability formulation is exact, while the LCL-reachability algorithm yields a sound approximation. We have applied the LCL-reachability framework to two existing client analyses. The experimental results show that the LCL-reachability framework is both more precise and scalable than the traditional CFL-reachability framework. This paper opens up the opportunity to exploit LCL-reachability in program analysis.}, + booktitle = {Proceedings of the 44th ACM SIGPLAN Symposium on Principles of Programming Languages}, + pages = {344–358}, + numpages = {15}, + keywords = {program analysis, Context-free language reachability, linear conjunctive grammar, trellis automata}, + location = {Paris, France}, + series = {POPL '17} +} + +@inproceedings{10.1007/978-3-662-59620-3_5, + author = {Kogkalidis, Konstantinos + and Melkonian, Orestis}, + editor = {Sikos, Jennifer + and Pacuit, Eric}, + title = {Towards a 2-Multiple Context-Free Grammar for the 3-Dimensional Dyck Language}, + booktitle = {At the Intersection of Language, Logic, and Information}, + year = {2019}, + publisher = {Springer Berlin Heidelberg}, + address = {Berlin, Heidelberg}, + pages = {79--92}, + abstract = {We discuss the open problem of parsing the Dyck language of 3 symbols, {\$}{\$}D^3{\$}{\$}, using a 2-Multiple Context-Free Grammar. We attempt to tackle this problem by implementing a number of novel meta-grammatical techniques and present the associated software packages we developed.}, + isbn = {978-3-662-59620-3} +} + +@inproceedings{Economopoulos2006GeneralisedLP, + title = {Generalised LR parsing algorithms}, + author = {Giorgios Economopoulos}, + year = {2006}, + url = {https://api.semanticscholar.org/CorpusID:29026667} +} + +@inproceedings{Cappers2014ExploringAV, + title = {Exploring and visualizing GLL parsing}, + author = {Bcm Bram Cappers}, + year = {2014}, + url = {https://api.semanticscholar.org/CorpusID:63190886} +} + +@inproceedings{Afroozeh2019PracticalGT, + title = {Practical general top-down parsers}, + author = {Ali Afroozeh and Anastasia Izmaylova}, + year = {2019}, + url = {https://api.semanticscholar.org/CorpusID:198351560} +} + +@article{10.1145/3571252, + author = {Koutris, Paraschos and Deep, Shaleen}, + title = {The Fine-Grained Complexity of CFL Reachability}, + year = {2023}, + issue_date = {January 2023}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {7}, + number = {POPL}, + url = {https://doi.org/10.1145/3571252}, + doi = {10.1145/3571252}, + abstract = {Many problems in static program analysis can be modeled as the context-free language (CFL) reachability problem on directed labeled graphs. The CFL reachability problem can be generally solved in time O(n3), where n is the number of vertices in the graph, with some specific cases that can be solved faster. In this work, we ask the following question: given a specific CFL, what is the exact exponent in the monomial of the running time? In other words, for which cases do we have linear, quadratic or cubic algorithms, and are there problems with intermediate runtimes? This question is inspired by recent efforts to classify classic problems in terms of their exact polynomial complexity, known as fine-grained complexity. Although recent efforts have shown some conditional lower bounds (mostly for the class of combinatorial algorithms), a general picture of the fine-grained complexity landscape for CFL reachability is missing. Our main contribution is lower bound results that pinpoint the exact running time of several classes of CFLs or specific CFLs under widely believed lower bound conjectures (e.g., Boolean Matrix Multiplication, k-Clique, APSP, 3SUM). We particularly focus on the family of Dyck-k languages (which are strings with well-matched parentheses), a fundamental class of CFL reachability problems. Remarkably, we are able to show a Ω(n2.5) lower bound for Dyck-2 reachability, which to the best of our knowledge is the first super-quadratic lower bound that applies to all algorithms, and shows that CFL reachability is strictly harder that Boolean Matrix Multiplication. We also present new lower bounds for the case of sparse input graphs where the number of edges m is the input parameter, a common setting in the database literature. For this setting, we show a cubic lower bound for Andersen’s Pointer Analysis which significantly strengthens prior known results.}, + journal = {Proc. ACM Program. Lang.}, + month = {jan}, + articleno = {59}, + numpages = {27}, + keywords = {sparse graphs, static pointer analysis, Dyck reachability, Datalog, fine-grained complexity} +} + +@misc{istomina2023finegrained, + title = {Fine-grained reductions around CFL-reachability}, + author = {Aleksandra Istomina and Semyon Grigorev and Ekaterina Shemetova}, + year = {2023}, + eprint = {2306.15967}, + archiveprefix = {arXiv}, + primaryclass = {cs.CC} +} + +@article{10.1145/3583660.3583664, + author = {Pavlogiannis, Andreas}, + title = {CFL/Dyck Reachability: An Algorithmic Perspective}, + year = {2023}, + issue_date = {October 2022}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {9}, + number = {4}, + url = {https://doi.org/10.1145/3583660.3583664}, + doi = {10.1145/3583660.3583664}, + abstract = {CFL/Dyck reachability is a simple graph-theoretic problem: given a CFL/Dyck language L over an alphabet Σ, a graph G = (V, E) of Σ-labeled edges, and two distinguished nodes s, t ∈ V, does there exist a path from s to t that spells out a word in L? This simple notion of language-based graph reachability serves as the algorithmic formulation of a large number of problems in diverse domains, such as graph databases and program static analysis. This paper takes an algorithmic perspective on CFL/Dyck reachability, and overviews several recent advances concerning the decidability and complexity of the problem and some its close variants, as realized in the areas of automata theory and program verification.}, + journal = {ACM SIGLOG News}, + month = {feb}, + pages = {5–25}, + numpages = {21} +} + +@inproceedings{Terekhov2021MultipleSourceCP, + title = {Multiple-Source Context-Free Path Querying in Terms of Linear Algebra}, + author = {Arseniy Terekhov and Vlada Pogozhelskaya and Vadim Abzalov and Timur Zinnatulin and Semyon V. Grigorev}, + booktitle = {International Conference on Extending Database Technology}, + year = {2021}, + url = {https://api.semanticscholar.org/CorpusID:232284054} +} + +@article{10.1145/321239.321249, + author = {Brzozowski, Janusz A.}, + title = {Derivatives of Regular Expressions}, + year = {1964}, + issue_date = {Oct. 1964}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {11}, + number = {4}, + issn = {0004-5411}, + url = {https://doi.org/10.1145/321239.321249}, + doi = {10.1145/321239.321249}, + journal = {J. ACM}, + month = {oct}, + pages = {481–494}, + numpages = {14} +} + +@book{Leiss1999, + doi = {10.1007/978-1-4612-2156-2}, + url = {https://doi.org/10.1007/978-1-4612-2156-2}, + year = {1999}, + publisher = {Springer New York}, + author = {Ernst L. Leiss}, + title = {Language Equations} +} + +@article{MRYKHIN2023113829, + title = {The hardest language for grammars with context operators}, + journal = {Theoretical Computer Science}, + volume = {958}, + pages = {113829}, + year = {2023}, + issn = {0304-3975}, + doi = {https://doi.org/10.1016/j.tcs.2023.113829}, + url = {https://www.sciencedirect.com/science/article/pii/S0304397523001421}, + author = {Mikhail Mrykhin and Alexander Okhotin}, + keywords = {Formal language theory, Formal grammars, Hardest formal languages, Grammars with context operators, Inverse homomorphisms, Finite transducers}, + abstract = {In 1973, Greibach (“The hardest context-free language”, SIAM J. Comp., 1973) constructed a context-free language L0 with the property that every context-free language can be reduced to L0 by a homomorphism, thus representing it as an inverse homomorphic image h−1(L0). In this paper, a similar characterization is established for a family of grammars equipped with operators for referring to the left context of any substring, recently defined by Barash and Okhotin (“An extension of context-free grammars with one-sided context specifications”, Inform. Comput., 2014). An essential step of the argument is a new normal form for grammars with context operators, in which every nonterminal symbol defines only strings of odd length in left contexts of even length: the even-odd normal form. The characterization is completed by showing that the language family defined by grammars with context operators is closed under inverse homomorphisms; actually, it is closed under injective nondeterministic finite transductions.} +} + +@article{markov1954theory, + title = {The theory of algorithms}, + author = {Markov, Andrei Andreevich}, + journal = {Trudy Matematicheskogo Instituta Imeni VA Steklova}, + volume = {42}, + pages = {3--375}, + year = {1954}, + publisher = {Russian Academy of Sciences, Steklov Mathematical Institute of Russian~…} +} + +@book{10.5555/578595, + author = {Harrison, M. A.}, + title = {Introduction to Formal Language Theory}, + year = {1978}, + isbn = {0201029553}, + publisher = {Addison-Wesley Longman Publishing Co., Inc.}, + address = {USA}, + edition = {1st}, + abstract = {From the Publisher:Formal language theory was fist developed in the mid 1950's in an attempt to develop theories of natural language acquisition. It was soon realized that this theory (particularly the context-free portion) was quite relevant to the artificial languages that had originated in computer science. Since those days, the theory of formal languages has been developed extensively, and has several discernible trends, which include applications to the syntactic analysis of programming languages, program schemes, models of biological systems, and relationships with natural languages.} +} + +@book{hopcroft2001introduction, + title = {Introduction to automata theory, languages, and computation}, + author = {Hopcroft, John E and Motwani, Rajeev and Ullman, Jeffrey D}, + journal = {Acm Sigact News}, + volume = {32}, + number = {1}, + pages = {60--65}, + year = {2001}, + publisher = {ACM New York, NY, USA} +} + +@article{10.1145/3591472, + author = {Jia, Xiaodong and Kumar, Ashish and Tan, Gang}, + title = {A Derivative-Based Parser Generator for Visibly Pushdown Grammars}, + year = {2023}, + issue_date = {June 2023}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {45}, + number = {2}, + issn = {0164-0925}, + url = {https://doi.org/10.1145/3591472}, + doi = {10.1145/3591472}, + abstract = {In this article, we present a derivative-based, functional recognizer and parser generator for visibly pushdown grammars. The generated parser accepts ambiguous grammars and produces a parse forest containing all valid parse trees for an input string in linear time. Each parse tree in the forest can then be extracted also in linear time. Besides the parser generator, to allow more flexible forms of the visibly pushdown grammars, we also present a translator that converts a tagged CFG to a visibly pushdown grammar in a sound way, and the parse trees of the tagged CFG are further produced by running the semantic actions embedded in the parse trees of the translated visibly pushdown grammar. The performance of the parser is compared with popular parsing tools, including ANTLR, GNU Bison, and other popular hand-crafted parsers. The correctness and the time complexity of the core parsing algorithm are formally verified in the proof assistant Coq.}, + journal = {ACM Trans. Program. Lang. Syst.}, + month = {may}, + articleno = {9}, + numpages = {68}, + keywords = {Parser generators, derivative-based parsing, formal verification} +} + +@inproceedings{10.1145/2983990.2984026, + author = {Brachth\"{a}user, Jonathan Immanuel and Rendel, Tillmann and Ostermann, Klaus}, + title = {Parsing with First-Class Derivatives}, + year = {2016}, + isbn = {9781450344449}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + url = {https://doi.org/10.1145/2983990.2984026}, + doi = {10.1145/2983990.2984026}, + abstract = {Brzozowski derivatives, well known in the context of regular expressions, have recently been rediscovered to give a simplified explanation to parsers of context-free languages. We add derivatives as a novel first-class feature to a standard parser combinator language. First-class derivatives enable an inversion of the control flow, allowing to implement modular parsers for languages that previously required separate pre-processing steps or cross-cutting modifications of the parsers. We show that our framework offers new opportunities for reuse and supports a modular definition of interesting use cases of layout-sensitive parsing.}, + booktitle = {Proceedings of the 2016 ACM SIGPLAN International Conference on Object-Oriented Programming, Systems, Languages, and Applications}, + pages = {588–606}, + numpages = {19}, + keywords = {Left Quotient, Parser Combinators, Parsing, Derivative, Modularity}, + location = {Amsterdam, Netherlands}, + series = {OOPSLA 2016} +} + +@article{10.1145/3022671.2984026, + author = {Brachth\"{a}user, Jonathan Immanuel and Rendel, Tillmann and Ostermann, Klaus}, + title = {Parsing with First-Class Derivatives}, + year = {2016}, + issue_date = {October 2016}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {51}, + number = {10}, + issn = {0362-1340}, + url = {https://doi.org/10.1145/3022671.2984026}, + doi = {10.1145/3022671.2984026}, + abstract = {Brzozowski derivatives, well known in the context of regular expressions, have recently been rediscovered to give a simplified explanation to parsers of context-free languages. We add derivatives as a novel first-class feature to a standard parser combinator language. First-class derivatives enable an inversion of the control flow, allowing to implement modular parsers for languages that previously required separate pre-processing steps or cross-cutting modifications of the parsers. We show that our framework offers new opportunities for reuse and supports a modular definition of interesting use cases of layout-sensitive parsing.}, + journal = {SIGPLAN Not.}, + month = {oct}, + pages = {588–606}, + numpages = {19}, + keywords = {Left Quotient, Parsing, Modularity, Derivative, Parser Combinators} +} + +@article{caron_champarnaud_mignot_2014, + title = {A general framework for the derivation of regular expressions}, + volume = {48}, + doi = {10.1051/ita/2014010}, + number = {3}, + journal = {RAIRO - Theoretical Informatics and Applications}, + publisher = {EDP Sciences}, + author = {Caron, Pascal and Champarnaud, Jean-Marc and Mignot, Ludovic}, + year = {2014}, + pages = {281–305} +} + +@article{10.1145/2034574.2034801, + author = {Might, Matthew and Darais, David and Spiewak, Daniel}, + title = {Parsing with Derivatives: A Functional Pearl}, + year = {2011}, + issue_date = {September 2011}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {46}, + number = {9}, + issn = {0362-1340}, + url = {https://doi.org/10.1145/2034574.2034801}, + doi = {10.1145/2034574.2034801}, + abstract = {We present a functional approach to parsing unrestricted context-free grammars based on Brzozowski's derivative of regular expressions. If we consider context-free grammars as recursive regular expressions, Brzozowski's equational theory extends without modification to context-free grammars (and it generalizes to parser combinators). The supporting actors in this story are three concepts familiar to functional programmers - laziness, memoization and fixed points; these allow Brzozowski's original equations to be transliterated into purely functional code in about 30 lines spread over three functions.Yet, this almost impossibly brief implementation has a drawback: its performance is sour - in both theory and practice. The culprit? Each derivative can double the size of a grammar, and with it, the cost of the next derivative.Fortunately, much of the new structure inflicted by the derivative is either dead on arrival, or it dies after the very next derivative. To eliminate it, we once again exploit laziness and memoization to transliterate an equational theory that prunes such debris into working code. Thanks to this compaction, parsing times become reasonable in practice.We equip the functional programmer with two equational theories that, when combined, make for an abbreviated understanding and implementation of a system for parsing context-free languages.}, + journal = {SIGPLAN Not.}, + month = {sep}, + pages = {189–195}, + numpages = {7}, + keywords = {derivative, context-free grammar, regular expressions, parsing, parser combinator, formal languages} +} + +@inproceedings{10.1145/2034773.2034801, + author = {Might, Matthew and Darais, David and Spiewak, Daniel}, + title = {Parsing with Derivatives: A Functional Pearl}, + year = {2011}, + isbn = {9781450308656}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + url = {https://doi.org/10.1145/2034773.2034801}, + doi = {10.1145/2034773.2034801}, + abstract = {We present a functional approach to parsing unrestricted context-free grammars based on Brzozowski's derivative of regular expressions. If we consider context-free grammars as recursive regular expressions, Brzozowski's equational theory extends without modification to context-free grammars (and it generalizes to parser combinators). The supporting actors in this story are three concepts familiar to functional programmers - laziness, memoization and fixed points; these allow Brzozowski's original equations to be transliterated into purely functional code in about 30 lines spread over three functions.Yet, this almost impossibly brief implementation has a drawback: its performance is sour - in both theory and practice. The culprit? Each derivative can double the size of a grammar, and with it, the cost of the next derivative.Fortunately, much of the new structure inflicted by the derivative is either dead on arrival, or it dies after the very next derivative. To eliminate it, we once again exploit laziness and memoization to transliterate an equational theory that prunes such debris into working code. Thanks to this compaction, parsing times become reasonable in practice.We equip the functional programmer with two equational theories that, when combined, make for an abbreviated understanding and implementation of a system for parsing context-free languages.}, + booktitle = {Proceedings of the 16th ACM SIGPLAN International Conference on Functional Programming}, + pages = {189–195}, + numpages = {7}, + keywords = {regular expressions, context-free grammar, parser combinator, formal languages, derivative, parsing}, + location = {Tokyo, Japan}, + series = {ICFP '11} +} + +@article{10.1017/S0956796808007090, + author = {Owens, Scott and Reppy, John and Turon, Aaron}, + title = {Regular-Expression Derivatives Re-Examined}, + year = {2009}, + issue_date = {March 2009}, + publisher = {Cambridge University Press}, + address = {USA}, + volume = {19}, + number = {2}, + issn = {0956-7968}, + url = {https://doi.org/10.1017/S0956796808007090}, + doi = {10.1017/S0956796808007090}, + abstract = {Regular-expression derivatives are an old, but elegant, technique for compiling regular expressions to deterministic finite-state machines. It easily supports extending the regular-expression operators with boolean operations, such as intersection and complement. Unfortunately, this technique has been lost in the sands of time and few computer scientists are aware of it. In this paper, we reexamine regular-expression derivatives and report on our experiences in the context of two different functional-language implementations. The basic implementation is simple and we show how to extend it to handle large character sets (e.g., Unicode). We also show that the derivatives approach leads to smaller state machines than the traditional algorithm given by McNaughton and Yamada.}, + journal = {J. Funct. Program.}, + month = {mar}, + pages = {173–190}, + numpages = {18} +} + +@inproceedings{10.1145/2949689.2949711, + author = {Nol\'{e}, Maurizio and Sartiani, Carlo}, + title = {Regular Path Queries on Massive Graphs}, + year = {2016}, + isbn = {9781450342155}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + url = {https://doi.org/10.1145/2949689.2949711}, + doi = {10.1145/2949689.2949711}, + abstract = {Regular Path Queries (RPQs) represent a powerful tool for querying graph databases and are of particular interest, because they form the building blocks of other query languages, and because they can be used in many theoretical or practical contexts for different purposes.In this paper we present a novel system for processing regular path queries on massive data graphs. As confirmed by an extensive experimental evaluation, our system scales linearly with the number of vertices and/or edges, and it can efficiently query graphs up to a billion vertices and 100 billion edges.}, + booktitle = {Proceedings of the 28th International Conference on Scientific and Statistical Database Management}, + articleno = {13}, + numpages = {12}, + location = {Budapest, Hungary}, + series = {SSDBM '16} +} + +@article{chomsky1958finite, + title = {Finite state languages}, + author = {Chomsky, Noam and Miller, George A}, + journal = {Information and control}, + volume = {1}, + number = {2}, + pages = {91--112}, + year = {1958}, + publisher = {Elsevier} +} diff --git a/tex/Introduction.tex b/tex/Introduction.tex new file mode 100644 index 0000000..6569c81 --- /dev/null +++ b/tex/Introduction.tex @@ -0,0 +1,78 @@ +\addchap{Введение} + +Теория формальных языков находит применение не только в ставших уже классическими задачах синтаксического анализа кода (языков программирования, искусственных языков) и естественных языков, но и в других областях, таких как статический анализ кода, графовые базы данных, биоинформатика, машинное обучение. + +Например, в машинном обучении использование формальных грамматик позволяет передать искусственной генеративной нейронной сети, предназначенной для построения цепочек с определёнными свойствами, знания о синтаксической структуре этих цепочек, что позволяет существенно упростить процесс обучения и повысить качество результата~\sidecite{10.5555/3305381.3305582}. +Вместе с этим, развиваются подходы, позволяющие нейронным сетям наоборот извлекать синтаксическую структуру (строить дерево вывода) для входных цепочек~\sidecite{kasai-etal-2017-tag,kasai-etal-2018-end}. + +В биоинформатике формальные грамматики нашли широкое применение для описания особенностей вторичной структуры геномных и белковых последовательностей~\sidecite{Dyrka2019,WJAnderson2012,zier2013rna}. +Соответствующие алгоритмы синтаксического анализа используются при создании инструментов обработки данных. + +Таким образом, теория формальных языков выступает в качестве основы для многих прикладных областей, а алгоритмы синтаксического анализа применимы не только для обработки естественных языков или языков программирования. +Нас же в данной работе будет интересовать применение теории формальных языков и алгоритмов синтаксического анализа для анализа графовых баз данных и для статического анализа кода. + +Одна из классических задач, связанных с анализом графов --- это поиск путей в графе. +Возможны различные формулировки этой задачи. +В некоторых случаях необходимо выяснить, существует ли путь с определёнными свойствами между двумя выбранными вершинами. +В других же ситуациях необходимо найти все пути в графе, удовлетворяющие некоторым свойствам или ограничениям. +Например, в качестве ограничений можно указать, что искомый путь должен быть простым, кратчайшим, гамильтоновым и так далее. + +Один из способов задавать ограничения на пути в графе основан на использовании формальных языков. +Базовое определение языка говорит нам, что язык --- это множество слов над некоторым алфавитом. +Если рассмотреть граф, рёбра которого помечены символами из алфавита, то путь в таком графе будет задавать слово: достаточно соединить последовательно символы, лежащие на рёбрах пути. +Множество же таких путей будет задавать множество слов или язык. +Таким образом, если мы хотим найти некоторое множество путей в графе, то в качестве ограничения можно описать язык, который должно задавать это множество. +Иными словами, задача поиска путей может быть сформулирована следующим образом: необходимо найти такие пути в графе, что слова, получаемые конкатенацией меток их рёбер, принадлежат заданному языку. +Такой класс задач будем называть задачами поиска путей с ограничениям в терминах формальных языков. + +Подобный класс задач часто возникает в областях, связанных с анализом граф-структурированных данных и активно исследуется~\sidecite{doi:10.1137/S0097539798337716,axelsson2011formal,10.1007/978-3-642-22321-1_24,Ward:2010:CRL:1710158.1710234,barrett2007label,doi:10.1137/S0097539798337716}. +Исследуются как классы языков, применяемых для задания ограничений, так и различные постановки задачи. + +Граф-структурированные данные встречаются не только в графовых базах данных, но и при статическом анализе кода: по программе можно построить различные графы отображающие её свойства. +Скажем, граф вызовов, граф потока данных и так далее. +Оказывается, что поиск путей в специального вида графах с использованием ограничений в терминах формальных языков позволяет исследовать некоторые нетривиальные свойства программы. +Например проводить межпроцедурный анализ указателей или анализ псевдонимов (алиасов)~\sidecite{Zheng,10.1145/2001420.2001440,10.1145/2714064.2660213}, строить срезы программ~\sidecite{10.1145/193173.195287}, проводить анализ типов~\sidecite{10.1145/373243.360208}. + +В данной работе представлен ряд алгоритмов для поиска путей с ограничениями в терминах формальных языков. +Основной акцент будет сделан на контекстно-свободных языках, однако будут затронуты и другие классы: регулярные, многокомпонентные контекстно-свободные (Multiple Context-Free Languages, MCFL~\sidecite{SEKI1991191}) и конъюнктивные языки. +Будет показано, что теория формальных языков и алгоритмы синтаксического анализа применимы не только для анализа языков программирования или естественных языков, а также для анализа графовых баз данных и статического анализа кода, что приводит к возникновению новых задач и переосмыслению старых. + + +Структура данной работы такова. +В начале (в части~\ref{chpt:GraphTheoryIntro}) мы рассмотрим основные понятия из теории графов, необходимые в данной работе. Данные разделы являются подготовительными и не обязательны к прочтению, если такие понятия как \textit{ориентированный граф} и \textit{матрица смежности} уже известны читателю. Более того, они лишь вводят определения, подразумевая, что более детальное изучение соответствующих разделов науки остается за рамками этой работы и скорее всего уже проделано читателем. +Затем, в главе~\ref{chpt:FormalLanguageTheoryIntro} мы введём основные понятия из теории формальных языков. +Далее, в главе~\ref{chpt:FLPQ} рассмотрим различные варианты постановки задачи поиска путей с ограничениями в терминах формальных языков, обсудим базовые свойства задач, её разрешимость в различных постановках и т.д.. +И в итоге зафиксируем постановку, которую будем изучать далее. +После этого, в главах~\ref{chpt:CFPQ_CYK}--\ref{chpt:GLR} мы будем подробно рассматривать различные алгоритмы решения этой задачи, попутно вводя специфичные для рассматриваемого алгоритма структуры данных. +Большинство алгоритмов будут основаны на классических алгоритмах синтаксического анализа, таких как CYK или LR. +%Все главы, начиная с~\ref{chpt:GraphTheoryIntro}, снабжены списком вопросов и задач для самостоятельного решения и закрепления материала. + +\begin{center} + \begin{tikzpicture}[shorten >=1pt,on grid,auto] + \node (q_linal) [text width=4cm] {Некоторые понятия линейной алгебры}; + \node (q_graphtheory) [below of=q_linal, text width=4cm] {Некоторые сведения из теории графов}; + \node (q_fortmallang) [right of=q_graphtheory, text width=4cm] {Общие сведения теории формальных языков}; + \node (q_reglang) [below of=q_fortmallang, text width=4cm] {Регулярные языки}; + \node (q_cflang) [right of=q_reglang, text width=4cm] {Контекстно-свободные языки и грамматики}; + \node (q_mcfl) [right of=q_cflang, text width=4cm] {Многокомпонентные контекстно-свободные языки}; + \node (q_flpq) [below of=q_graphtheory, text width=4cm] {Пути с ограничениями в терминах формальных языков}; + + \node (q_rpq) [below of=q_reglang, text width=4cm] {Поиск путей с регулярными ограничениями}; + \node (q_cfpq) [below of=q_cflang, text width=4cm] {Пути с ограничениями в терминах контекстно-свободных языков}; + \node (q_mcfpq) [below of=q_mcfl, text width=4cm] {Пути с ограничениями в терминах многокомпонентных контекстно-свободных языков}; + \path[->] + (q_linal) edge node {} (q_graphtheory) + (q_graphtheory) edge node {} (q_flpq) + (q_fortmallang) edge node {} (q_flpq) + (q_fortmallang) edge node {} (q_reglang) + (q_fortmallang) edge node {} (q_cflang) + (q_fortmallang) edge node {} (q_mcfl) + (q_reglang) edge node {} (q_rpq) + (q_cflang) edge node {} (q_cfpq) + (q_mcfl) edge node {} (q_mcfpq) + (q_flpq) edge node {} (q_rpq) + (q_flpq) edge node {} (q_cfpq) + (q_flpq) edge node {} (q_mcfpq) + ; + \end{tikzpicture} +\end{center} diff --git a/tex/kaobiblio.sty b/tex/kaobiblio.sty new file mode 100644 index 0000000..7ab8e50 --- /dev/null +++ b/tex/kaobiblio.sty @@ -0,0 +1,426 @@ +\ProvidesPackage{kaobiblio} + +%---------------------------------------------------------------------------------------- +% PACKAGE OPTIONS AND DEPENDENCIES +%---------------------------------------------------------------------------------------- + +\RequirePackage{etoolbox} % Easy programming to modify TeX stuff +\RequirePackage{perpage} % Reset counters +\RequirePackage{iflang} % Check the document language +\RequirePackage{xparse} % Parse arguments for macros +\RequirePackage{xstring} % Parse strings +\RequirePackage{hyperref} % Required for hyperlinks +\RequirePackage{kvoptions} % Handle package options + +% Set up the package options +\SetupKeyvalOptions{ + family = kaobiblio, + prefix = kaobiblio@ +} + +\DeclareBoolOption{addspace}% If true, automatically add a space before printing the citation marker +\DeclareBoolOption{linkeverything}% If true, the author name is a hyperlink in citation styles that support it + +% Choose the default options, which will be overwritten by the options +% passed to this package. +\PassOptionsToPackage{ + %style=numeric-comp, + %citestyle=authortitle-icomp, + citestyle=numeric-comp, + %bibstyle=authoryear, + bibstyle=numeric, + sorting=none, + %sorting=nyt, + %sortcites=true, + %autocite=footnote, + backend=biber, % Compile the bibliography with biber + hyperref=true, + backref=true, + citecounter=true, + pagetracker=true, + citetracker=true, + ibidtracker=context, + autopunct=true, + autocite=plain, +}{biblatex} + +% Pass the unknown options to biblatex, overwriting the previous settings. Avoid passing the kao-specific options. +\DeclareDefaultOption{% + \IfBeginWith{\CurrentOption}{addspace}{}{% + \IfBeginWith{\CurrentOption}{linkeverything}{}{% + \PassOptionsToPackage{\CurrentOption}{biblatex}% + }}% +} + +% Process the options +\ProcessKeyvalOptions{kaobiblio} + +% Load biblatex +\RequirePackage{biblatex} + +% Remove some unwanted entries from the bibliography +\AtEveryBibitem{ + \clearfield{issn} + \clearfield{isbn} + \clearfield{archivePrefix} + \clearfield{arxivId} + \clearfield{pmid} + \clearfield{eprint} + \ifentrytype{online}{}{\ifentrytype{misc}{}{\clearfield{url}}} + \ifentrytype{book}{\clearfield{doi}}{} +} + +% Convert months to integers +\DeclareSourcemap{ + \maps[datatype=bibtex]{ + \map[overwrite]{ + \step[fieldsource=month, match={jan}, replace=${1}] + \step[fieldsource=month, match={feb}, replace=${2}] + \step[fieldsource=month, match={mar}, replace=${3}] + \step[fieldsource=month, match={apr}, replace=${4}] + \step[fieldsource=month, match={may}, replace=${5}] + \step[fieldsource=month, match={jun}, replace=${6}] + \step[fieldsource=month, match={jul}, replace=${7}] + \step[fieldsource=month, match={aug}, replace=${8}] + \step[fieldsource=month, match={sep}, replace=${9}] + \step[fieldsource=month, match={oct}, replace=${10}] + \step[fieldsource=month, match={nov}, replace=${11}] + \step[fieldsource=month, match={dec}, replace=${12}] + } + } +} + +%---------------------------------------------------------------------------------------- +% BACK REFERENCES +%---------------------------------------------------------------------------------------- + +% Check if a string is in a comma-separated list +\newcommand\IfStringInList[2]{\IfSubStr{,#2,}{,#1,}} + +% Set the language-specific back reference strings +% #LANGUAGE +\@ifpackageloaded{polyglossia}{% + \IfLanguageName{danish}{% + \DefineBibliographyStrings{danish}{% + backrefpage = {citeret på side}, + backrefpages = {citeret på sider}, + } + }{} + \IfLanguageName{english}{% + \DefineBibliographyStrings{english}{% + backrefpage = {cited on page}, + backrefpages = {cited on pages}, + } + }{} + \IfLanguageName{italian}{% + \DefineBibliographyStrings{italian}{% + backrefpage = {citato a pag.}, + backrefpages = {citato a pagg.}, + } + }{} +}{ + \@ifpackageloaded{babel}{% + \IfStringInList{danish}{\bbl@loaded}{% + \DefineBibliographyStrings{danish}{% + backrefpage = {citeret på side}, + backrefpages = {citeret på sider}, + } + }{} + \IfStringInList{english}{\bbl@loaded}{% + \DefineBibliographyStrings{english}{% + backrefpage = {cited on page}, + backrefpages = {cited on pages}, + } + }{} + \IfStringInList{italian}{\bbl@loaded}{% + \DefineBibliographyStrings{italian}{% + backrefpage = {citato a pag.}, + backrefpages = {citato a pagg.}, + } + }{} + }{} +} + +%---------------------------------------------------------------------------------------- +% CITATION COMMANDS +%---------------------------------------------------------------------------------------- + +% Command to format the marginnote created for cited items +\NewDocumentCommand{\formatmargincitation}{m}{% The parameter is a single citation key + \parencite{#1}: \citeauthor*{#1} (\iffieldundef{year}{\bibsstring{nodate}}{\printfield{year}}), \citefield{#1}[emph]{title}% +} + +% Command to format the marginnote created for supercited items +\NewDocumentCommand{\formatmarginsupercitation}{m}{% The parameter is a single citation key + \supercite{#1} \citeauthor*{#1} (\iffieldundef{year}{\bibsstring{nodate}}{\printfield{year}})% +} + +% The following command needs to be redefined every time \sidecite is called in order for \DeclareCiteCommand's wrapper to work correctly +\NewDocumentCommand{\kaobiblio@marginnote}{m}{% + \marginnote{#1}% +} + +% biblatex-like commands that also print a citation in the margin +% Usage: + % First optional argument is always vertical shift and must be given as an (empty) argument when using following a postnote and/or prenote + % Second optional argument is always the postnote if the third argument isn't specified or is the prenote if the third argument is specified (same pattern as the biblatex commands) + % Third optional argument is always the postnote + % Mandatory argument is always the citation key(s) + +% Command to \cite and print a citation in the margin +% First optional argument: vertical shift +% Second optional argument: postnote if the third argument isn't specified; prenote if the third argument is specified (same pattern as the \textcite command) +% Third optional argument: postnote +% Mandatory argument: citation key +\NewDocumentCommand{\sidecite}{o o o m}{% + \RenewDocumentCommand{\kaobiblio@marginnote}{m}{% + \marginnote[#1]{##1}% + }% + \DeclareCiteCommand{\kaobiblio@sidecite}[\kaobiblio@marginnote]{% + }{% + \formatmargincitation{\thefield{entrykey}}% + }{% + \\% separator between multiple citations + }{% + }% + % With this we print the marker in the text and add the item to the bibliography at the end + \IfNoValueOrEmptyTF{#2}% + {\def\@tempa{\cite{#4}\kaobiblio@sidecite{#4}}}% + {\IfNoValueOrEmptyTF{#3}% + {\IfNoValueTF{#3}% + {\def\@tempa{\cite[#2]{#4}\kaobiblio@sidecite{#4}}}% + {\def\@tempa{\cite[#2][]{#4}\kaobiblio@sidecite{#4}}}% postnote is empty, so pass empty postnote + }% + {\def\@tempa{\cite[#2][#3]{#4}\kaobiblio@sidecite{#4}}}% + }% + \ifkaobiblio@addspace% + \unskip~\@tempa% + \else% + \@tempa% + \fi% +} + +% Command to \supercite and print a citation in the margin +% First optional argument: vertical shift +% Second optional argument: postnote if the third argument isn't specified; prenote if the third argument is specified (same pattern as the \textcite command) +% Third optional argument: postnote +% Mandatory argument: citation key +\NewDocumentCommand{\sidesupercite}{o o o m}{% + \RenewDocumentCommand{\kaobiblio@marginnote}{m}{% + \marginnote[#1]{##1}% + }% + \DeclareCiteCommand{\kaobiblio@sidesupercite}[\kaobiblio@marginnote]{% + }{% + \formatmarginsupercitation{\thefield{entrykey}}% + }{% + \\% separator between multiple citations + }{% + }% + % With this we print the marker in the text and add the item to the bibliography at the end + \IfNoValueOrEmptyTF{#2}% + {\def\@tempa{\supercite{#4}\kaobiblio@sidesupercite{#4}}}% + {\IfNoValueOrEmptyTF{#3}% + {\IfNoValueTF{#3}% + {\def\@tempa{\supercite[#2]{#4}\kaobiblio@sidesupercite{#4}}}% + {\def\@tempa{\supercite[#2][]{#4}\kaobook@sidesupercite{#4}}}% postnote is empty, so pass empty postnote + }% + {\def\@tempa{\supercite[#2][#3]{#4}\kaobiblio@sidesupercite{#4}}}% + }% + \@tempa% +} + +% Command to \textcite and print a citation in the margin +% First optional argument: vertical shift +% Second optional argument: postnote if the third argument isn't specified; prenote if the third argument is specified (same pattern as the \textcite command) +% Third optional argument: postnote +% Mandatory argument: citation key +\NewDocumentCommand{\sidetextcite}{o o o m}{% + \RenewDocumentCommand{\kaobiblio@marginnote}{m}{% + \marginnote[#1]{##1}% + }% + \DeclareCiteCommand{\kaobiblio@sidecite}[\kaobiblio@marginnote]{% + }{% + \formatmargincitation{\thefield{entrykey}}% + }{% + \\% separator between multiple citations + }{% + }% + % With this we print the marker in the text and add the item to the bibliography at the end + \IfNoValueOrEmptyTF{#2}% + {\def\@tempa{\textcite{#4}\kaobiblio@sidecite{#4}}}% + {\IfNoValueOrEmptyTF{#3}% + {\IfNoValueTF{#3}% + {\def\@tempa{\textcite[#2]{#4}\kaobiblio@sidecite{#4}}}% + {\def\@tempa{\textcite[#2][]{#4}\kaobook@sidecite{#4}}}% postnote is empty, so pass empty postnote + }% + {\def\@tempa{\textcite[#2][#3]{#4}\kaobiblio@sidecite{#4}}}% + }% + \ifkaobiblio@addspace% + \unskip~\@tempa% + \else% + \@tempa% + \fi% +} + +% Command to \parencite or \parencite* and print a citation in the margin +% First optional (star) argument: use \parencite* if included; otherwise use \parencite +% Second optional argument: vertical shift +% Third optional argument: postnote if the fourth argument isn't specified; prenote if the fourth argument is specified (same pattern as the \parencite command) +% Fourth optional argument: postnote +% Mandatory argument: citation key +\NewDocumentCommand{\sideparencite}{s o o o m}{% + \RenewDocumentCommand{\kaobiblio@marginnote}{m}{% + \marginnote[#2]{##1}% + }% + \DeclareCiteCommand{\kaobiblio@sidecite}[\kaobiblio@marginnote]{% + }{% + \formatmargincitation{\thefield{entrykey}}% + }{% + \\% separator between multiple citations + }{% + }% + % With this we print the marker in the text and add the item to the bibliography at the end + \IfBooleanTF#1% + {\IfNoValueOrEmptyTF{#3}% + {\parencite*{#5}\kaobiblio@sidecite{#5}}% + {\IfNoValueOrEmptyTF{#4}% + {\IfNoValueTF{#4}% + {\def\@tempa{\parencite*[#3]{#5}\kaobiblio@sidecite{#5}}}% + {\def\@tempa{\parencite*[#3][]{#5}\kaobiblio@sidecite{#5}}}% postnote is empty, so pass empty postnote + }% + {\def\@tempa{\parencite*[#3][#4]{#5}\kaobiblio@sidecite{#5}}}% + }% + }% + {\IfNoValueOrEmptyTF{#3}% + {\def\@tempa{\parencite{#5}\kaobiblio@sidecite{#5}}}% + {\IfNoValueOrEmptyTF{#4}% + {\IfNoValueTF{#4}% + {\def\@tempa{\parencite[#3]{#5}\kaobiblio@sidecite{#5}}}% + {\def\@tempa{\parencite[#3][]{#5}\kaobiblio@sidecite{#5}}}% postnote is empty, so pass empty postnote + }% + {\def\@tempa{\parencite[#3][#4]{#5}\kaobiblio@sidecite{#5}}}% + }% + }% + \ifkaobiblio@addspace% + \unskip~\@tempa% + \else% + \@tempa% + \fi% +} + + +%---------------------------------------------------------------------------------------- +% LINKING THE AUTHOR'S NAME +%---------------------------------------------------------------------------------------- + +% In biblatex, when citing with the style authoryear or using \textcite, only the year is linked to the reference in the bibliography. Despite the arguments of one of the mantainers of the biblatex package (https://github.com/plk/biblatex/issues/428), some users think that in the author* style the author name should be a link as well. The `linkeverything' option provides an easy way to activate this behaviour. + +\ifkaobiblio@linkeverything + \xpatchbibmacro{cite} + {\usebibmacro{cite:label}% + \setunit{\printdelim{nonameyeardelim}}% + \usebibmacro{cite:labeldate+extradate}} + {\printtext[bibhyperref]{% + \DeclareFieldAlias{bibhyperref}{default}% + \usebibmacro{cite:label}% + \setunit{\printdelim{nonameyeardelim}}% + \usebibmacro{cite:labeldate+extradate}}} + {} + {\PackageWarning{biblatex-patch} + {Failed to patch cite bibmacro}} + + % Include labelname in labelyear link + \xpatchbibmacro{cite} + {\printnames{labelname}% + \setunit{\printdelim{nameyeardelim}}% + \usebibmacro{cite:labeldate+extradate}} + {\printtext[bibhyperref]{% + \DeclareFieldAlias{bibhyperref}{default}% + \printnames{labelname}% + \setunit{\printdelim{nameyeardelim}}% + \usebibmacro{cite:labeldate+extradate}}} + {} + {\PackageWarning{biblatex-patch} + {Failed to patch cite bibmacro}} + + % Access hyperref's citation link start/end commands + \makeatletter + \protected\def\blx@imc@biblinkstart{% + \@ifnextchar[%] + {\blx@biblinkstart} + {\blx@biblinkstart[\abx@field@entrykey]}} + \def\blx@biblinkstart[#1]{% + \blx@sfsave\hyper@natlinkstart{\the\c@refsection @#1}\blx@sfrest} + \protected\def\blx@imc@biblinkend{% + \blx@sfsave\hyper@natlinkend\blx@sfrest} + \blx@regimcs{\biblinkstart \biblinkend} + \makeatother + + \newbool{cbx:link} + + % Include parentheses around labelyear in \textcite only in + % single citations without pre- and postnotes + \def\iflinkparens{% + \ifboolexpr{ test {\ifnumequal{\value{multicitetotal}}{0}} and + test {\ifnumequal{\value{citetotal}}{1}} and + test {\iffieldundef{prenote}} and + test {\iffieldundef{postnote}} }} + + \xpatchbibmacro{textcite} + {\printnames{labelname}} + {\iflinkparens + {\DeclareFieldAlias{bibhyperref}{default}% + \global\booltrue{cbx:link}\biblinkstart% + \printnames{labelname}} + {\printtext[bibhyperref]{\printnames{labelname}}}} + {} + {\PackageWarning{biblatex-patch} + {Failed to patch textcite bibmacro}} + + \xpatchbibmacro{textcite} + {\usebibmacro{cite:label}} + {\iflinkparens + {\DeclareFieldAlias{bibhyperref}{default}% + \global\booltrue{cbx:link}\biblinkstart% + \usebibmacro{cite:label}} + {\usebibmacro{cite:label}}} + {} + {\PackageWarning{biblatex-patch} + {Failed to patch textcite bibmacro}} + + \xpretobibmacro{textcite:postnote} + {\ifbool{cbx:link} + {\ifbool{cbx:parens} + {\bibcloseparen\global\boolfalse{cbx:parens}} + {}% + \biblinkend\global\boolfalse{cbx:link}} + {}} + {} + {\PackageWarning{biblatex-patch} + {Failed to patch textcite:postnote bibmacro}} +\else +\fi + +%---------------------------------------------------------------------------------------- +% CITATION ENVIRONMENTS +%---------------------------------------------------------------------------------------- + +% TODO: create a fancy environment for this. Perhaps printing also the +% abstract. + +% Cite commands (assuming biblatex is loaded) +\DeclareCiteCommand{\fullcite}{% + \defcounter{maxnames}{99}% + \usebibmacro{prenote}} + {\clearfield{url}% + \clearfield{pages}% + \clearfield{pagetotal}% + \clearfield{edition}% + \clearfield{issn}% + \clearfield{doi}% + \usedriver + {\DeclareNameAlias{sortname}{default}} + {\thefield{entrytype}} +} +{\multicitedelim} +{\usebibmacro{postnote}} diff --git a/tex/main.tex b/tex/main.tex index e208bcb..a07c86f 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -6,6 +6,9 @@ \input{styles/language.tex} \input{styles/utils.tex} +\usepackage{kaobiblio} +\addbibresource{FormalLanguageConstrainedReachabilityLectureNotes.bib} + \title{О достижимости с ограничениями в терминах формальных языков} \author{Семён Григорьев} \date{\today} @@ -20,5 +23,14 @@ \input{List_of_contributors} \mainmatter +\setchapterstyle{kao} +\setchapterpreamble[u]{\margintoc} + +\input{Introduction} + +\backmatter +\setchapterstyle{plain} + +\printbibliography \end{document} From d5058cb1402a5f3c64dcc585481c3c7d3f5e1f5b Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sat, 8 Jun 2024 23:09:31 +0300 Subject: [PATCH 06/29] Add -shell-escape to latexmk arguments --- .vscode/settings.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index c6e97ba..6ed6f7e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,4 +25,20 @@ "files.insertFinalNewline": true, "files.trimFinalNewlines": true, "files.trimTrailingWhitespace": true, + "latex-workshop.latex.tools": [ + { + "name": "lualatexmk", + "command": "latexmk", + "args": [ + "-synctex=1", + "-interaction=nonstopmode", + "-file-line-error", + "-lualatex", + "-shell-escape", + "-outdir=%OUTDIR%", + "%DOC%" + ], + "env": {} + }, + ], } From 5568b45edff8784ca5c48e08ed0cc5a8c5bfbafa Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sat, 8 Jun 2024 23:12:29 +0300 Subject: [PATCH 07/29] Minor fixes in introduction & basic TikZ setup TikZ externalized enabled by default. Also made changes to the dependency diagram, maybe in vain --- .gitignore | 1 + tex/Introduction.tex | 73 +++++++++++++++++++++++++------------------- tex/main.tex | 3 ++ tex/styles/tikz.tex | 10 ++++++ 4 files changed, 55 insertions(+), 32 deletions(-) create mode 100644 tex/styles/tikz.tex diff --git a/.gitignore b/.gitignore index 6d8abb8..8c7636a 100644 --- a/.gitignore +++ b/.gitignore @@ -276,3 +276,4 @@ TSWLatexianTemp* *.lpz tex/FormalLanguageConstrainedReachabilityLectureNotes.pdf +tex/figures/externalized/* diff --git a/tex/Introduction.tex b/tex/Introduction.tex index 6569c81..ece901c 100644 --- a/tex/Introduction.tex +++ b/tex/Introduction.tex @@ -11,14 +11,14 @@ Таким образом, теория формальных языков выступает в качестве основы для многих прикладных областей, а алгоритмы синтаксического анализа применимы не только для обработки естественных языков или языков программирования. Нас же в данной работе будет интересовать применение теории формальных языков и алгоритмов синтаксического анализа для анализа графовых баз данных и для статического анализа кода. -Одна из классических задач, связанных с анализом графов --- это поиск путей в графе. +Одна из классических задач, связанных с анализом графов~--- это поиск путей в графе. Возможны различные формулировки этой задачи. В некоторых случаях необходимо выяснить, существует ли путь с определёнными свойствами между двумя выбранными вершинами. В других же ситуациях необходимо найти все пути в графе, удовлетворяющие некоторым свойствам или ограничениям. Например, в качестве ограничений можно указать, что искомый путь должен быть простым, кратчайшим, гамильтоновым и так далее. Один из способов задавать ограничения на пути в графе основан на использовании формальных языков. -Базовое определение языка говорит нам, что язык --- это множество слов над некоторым алфавитом. +Базовое определение языка говорит нам, что язык~--- это множество слов над некоторым алфавитом. Если рассмотреть граф, рёбра которого помечены символами из алфавита, то путь в таком графе будет задавать слово: достаточно соединить последовательно символы, лежащие на рёбрах пути. Множество же таких путей будет задавать множество слов или язык. Таким образом, если мы хотим найти некоторое множество путей в графе, то в качестве ограничения можно описать язык, который должно задавать это множество. @@ -37,9 +37,9 @@ Основной акцент будет сделан на контекстно-свободных языках, однако будут затронуты и другие классы: регулярные, многокомпонентные контекстно-свободные (Multiple Context-Free Languages, MCFL~\sidecite{SEKI1991191}) и конъюнктивные языки. Будет показано, что теория формальных языков и алгоритмы синтаксического анализа применимы не только для анализа языков программирования или естественных языков, а также для анализа графовых баз данных и статического анализа кода, что приводит к возникновению новых задач и переосмыслению старых. - Структура данной работы такова. -В начале (в части~\ref{chpt:GraphTheoryIntro}) мы рассмотрим основные понятия из теории графов, необходимые в данной работе. Данные разделы являются подготовительными и не обязательны к прочтению, если такие понятия как \textit{ориентированный граф} и \textit{матрица смежности} уже известны читателю. Более того, они лишь вводят определения, подразумевая, что более детальное изучение соответствующих разделов науки остается за рамками этой работы и скорее всего уже проделано читателем. +В начале (в части~\ref{chpt:GraphTheoryIntro}) мы рассмотрим основные понятия из теории графов, необходимые в данной работе. Данные разделы являются подготовительными и не обязательны к прочтению, если такие понятия как \textit{ориентированный граф} и \textit{матрица смежности} уже известны читателю. +Более того, они лишь вводят определения, подразумевая, что более детальное изучение соответствующих разделов науки остается за рамками этой работы и скорее всего уже проделано читателем. Затем, в главе~\ref{chpt:FormalLanguageTheoryIntro} мы введём основные понятия из теории формальных языков. Далее, в главе~\ref{chpt:FLPQ} рассмотрим различные варианты постановки задачи поиска путей с ограничениями в терминах формальных языков, обсудим базовые свойства задач, её разрешимость в различных постановках и т.д.. И в итоге зафиксируем постановку, которую будем изучать далее. @@ -47,32 +47,41 @@ Большинство алгоритмов будут основаны на классических алгоритмах синтаксического анализа, таких как CYK или LR. %Все главы, начиная с~\ref{chpt:GraphTheoryIntro}, снабжены списком вопросов и задач для самостоятельного решения и закрепления материала. -\begin{center} - \begin{tikzpicture}[shorten >=1pt,on grid,auto] - \node (q_linal) [text width=4cm] {Некоторые понятия линейной алгебры}; - \node (q_graphtheory) [below of=q_linal, text width=4cm] {Некоторые сведения из теории графов}; - \node (q_fortmallang) [right of=q_graphtheory, text width=4cm] {Общие сведения теории формальных языков}; - \node (q_reglang) [below of=q_fortmallang, text width=4cm] {Регулярные языки}; - \node (q_cflang) [right of=q_reglang, text width=4cm] {Контекстно-свободные языки и грамматики}; - \node (q_mcfl) [right of=q_cflang, text width=4cm] {Многокомпонентные контекстно-свободные языки}; - \node (q_flpq) [below of=q_graphtheory, text width=4cm] {Пути с ограничениями в терминах формальных языков}; +\begin{figure*} + \begin{center} + \begin{tikzpicture}[shorten >= 1pt, + auto, + node distance=0.5cm, + every node/.style = {shape=rectangle, draw, rounded corners}, + align = center] + \node (q_linal) {Некоторые понятия \\ линейной алгебры}; + + \node (q_graphtheory) [below = of q_linal, ] {Некоторые сведения \\ из теории графов}; + \node (q_fortmallang) [right = 2 of q_graphtheory] {Общие сведения теории \\ формальных языков}; + + \node (q_flpq) [below = of q_graphtheory] {Пути с ограничениями \\ в терминах формальных \\ языков}; + \node (q_reglang) [right = of q_flpq] {Регулярные \\ языки}; + \node (q_cflang) [right = of q_reglang] {Контекстно-свободные \\ языки и грамматики}; + \node (q_mcfl) [right = of q_cflang] {Многокомпонентные \\ контекстно-свободные \\ языки}; + + \node (q_rpq) [below = 2 of q_flpq] {Поиск путей \\ с регулярными \\ ограничениями}; + \node (q_cfpq) [below = 2 of q_reglang] {Пути с ограничениями \\ в терминах \\ контекстно-свободных \\ языков}; + \node (q_mcfpq) [right = of q_cfpq] {Пути с ограничениями \\ в терминах \\ многокомпонентных \\ контекстно-свободных \\ языков}; - \node (q_rpq) [below of=q_reglang, text width=4cm] {Поиск путей с регулярными ограничениями}; - \node (q_cfpq) [below of=q_cflang, text width=4cm] {Пути с ограничениями в терминах контекстно-свободных языков}; - \node (q_mcfpq) [below of=q_mcfl, text width=4cm] {Пути с ограничениями в терминах многокомпонентных контекстно-свободных языков}; - \path[->] - (q_linal) edge node {} (q_graphtheory) - (q_graphtheory) edge node {} (q_flpq) - (q_fortmallang) edge node {} (q_flpq) - (q_fortmallang) edge node {} (q_reglang) - (q_fortmallang) edge node {} (q_cflang) - (q_fortmallang) edge node {} (q_mcfl) - (q_reglang) edge node {} (q_rpq) - (q_cflang) edge node {} (q_cfpq) - (q_mcfl) edge node {} (q_mcfpq) - (q_flpq) edge node {} (q_rpq) - (q_flpq) edge node {} (q_cfpq) - (q_flpq) edge node {} (q_mcfpq) - ; - \end{tikzpicture} -\end{center} + \path[->] + (q_linal) edge (q_graphtheory) + (q_graphtheory) edge (q_flpq) + (q_fortmallang) edge (q_flpq) + (q_fortmallang) edge (q_reglang) + (q_fortmallang) edge (q_cflang) + (q_fortmallang) edge (q_mcfl) + (q_reglang) edge (q_rpq) + (q_cflang) edge (q_cfpq) + (q_mcfl) edge (q_mcfpq) + (q_flpq) edge (q_rpq) + (q_flpq) edge (q_cfpq) + (q_flpq) edge (q_mcfpq); + \end{tikzpicture} + \end{center} + \caption{Структура данной книги} +\end{figure*} diff --git a/tex/main.tex b/tex/main.tex index a07c86f..57e1f54 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -5,10 +5,13 @@ \input{styles/language.tex} \input{styles/utils.tex} +\input{styles/tikz.tex} \usepackage{kaobiblio} \addbibresource{FormalLanguageConstrainedReachabilityLectureNotes.bib} +\tikzexternalize + \title{О достижимости с ограничениями в терминах формальных языков} \author{Семён Григорьев} \date{\today} diff --git a/tex/styles/tikz.tex b/tex/styles/tikz.tex new file mode 100644 index 0000000..34609f5 --- /dev/null +++ b/tex/styles/tikz.tex @@ -0,0 +1,10 @@ +\usepackage{tikz} +\usetikzlibrary{arrows.meta} +\usetikzlibrary{external} +\usetikzlibrary{positioning} + +\tikzsetexternalprefix{figures/externalized/} + +% \usetikzlibrary{fit, calc, automata} +% \usetikzlibrary{shapes.geometric} +% \usetikzlibrary{decorations.pathmorphing} From 1af1bb9ff05a01ccba133af07bc6a226c49e98ae Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sat, 8 Jun 2024 23:15:15 +0300 Subject: [PATCH 08/29] Enable microtype and specify font size --- tex/main.tex | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tex/main.tex b/tex/main.tex index 57e1f54..2a0cf89 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -1,4 +1,5 @@ \documentclass[ + fontsize=10pt, a4paper, twoside=false ]{kaobook} @@ -7,6 +8,8 @@ \input{styles/utils.tex} \input{styles/tikz.tex} +\usepackage{microtype} + \usepackage{kaobiblio} \addbibresource{FormalLanguageConstrainedReachabilityLectureNotes.bib} From ec9130bda688dad7831df690b42363dffce6027a Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sun, 9 Jun 2024 21:23:08 +0300 Subject: [PATCH 09/29] Fix .bib file Remove \CYR commands --- tex/FormalLanguageConstrainedReachabilityLectureNotes.bib | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tex/FormalLanguageConstrainedReachabilityLectureNotes.bib b/tex/FormalLanguageConstrainedReachabilityLectureNotes.bib index 2548972..6adf3ab 100644 --- a/tex/FormalLanguageConstrainedReachabilityLectureNotes.bib +++ b/tex/FormalLanguageConstrainedReachabilityLectureNotes.bib @@ -1467,7 +1467,7 @@ @article{BEATTY1980193 @misc{VavilovGroups, language = {russian}, - author = {{\CYRN}иколай Вавилов}, + author = {Николай Вавилов}, title = {КОНКРЕТНАЯ ТЕОРИЯ ГРУПП}, year = {2005}, url = {http://dobrochan.com/src/pdf/1512/Вавилов-Н.-Конкретная-теория-групп.-Основные-понят.pdf}, @@ -1477,7 +1477,7 @@ @misc{VavilovGroups @misc{VavilovRings, language = {russian}, - author = {{\CYRN}иколай Вавилов}, + author = {Николай Вавилов}, title = {КОНКРЕТНАЯ ТЕОРИЯ КОЛЕЦ}, year = {2006}, url = {http://www.add3d.ru/wp-content/uploads/2019/10/Vavilov-Rings.pdf}, @@ -1531,7 +1531,7 @@ @inproceedings{10.1007/978-3-662-47672-7_89 @article{ArlDinKro70, - author = {{\CYRV}. Арлазаров and {\CYRE}. Диниц and {\CYRM}. Кронрод and {\CYRI}. Фараджев}, + author = {В. Арлазаров and Е. Диниц and М. Кронрод and И. Фараджев}, title = {Об экономном построении транзитивного замыкания ориентированного графа}, journal = {Докл. АН СССР}, year = {1970}, From 4bc4b6dfb03904ac4b08aa18d9489d51bd8ed0b9 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Wed, 12 Jun 2024 23:32:44 +0300 Subject: [PATCH 10/29] Add Linear Algebra chapter Also ton of styling and reformating --- tex/LinearAlgebra.tex | 815 ++++++++++++++++++++++++++++++++++++++++ tex/main.tex | 17 +- tex/styles/language.tex | 3 + tex/styles/math.tex | 8 + tex/styles/theorems.tex | 66 ++++ tex/styles/utils.tex | 2 + 6 files changed, 906 insertions(+), 5 deletions(-) create mode 100644 tex/LinearAlgebra.tex create mode 100644 tex/styles/math.tex create mode 100644 tex/styles/theorems.tex diff --git a/tex/LinearAlgebra.tex b/tex/LinearAlgebra.tex new file mode 100644 index 0000000..b9527fd --- /dev/null +++ b/tex/LinearAlgebra.tex @@ -0,0 +1,815 @@ +\setchapterpreamble[u]{\margintoc} +\chapter{Некоторые понятия линейной алгебры} +\label{chpt:LinAlIntro} + +При изложении ряда алгоритмов будут активно использоваться некоторые понятия и инструменты линейной алгебры, такие как моноид, полукольцо или матрица. +В данном разделе необходимые понятия будут определены и приведены некоторые примеры соответствующих конструкций. +Для более глубокого изучения материала рекомендуются обратиться к соответствующим разделам алгебры. +\marginnote[*6]{ + Неообходимо понимать, что, с одной строны, в данном разделе рассматриваются самые базовые понятия, которые даются практически в любом учебнике алгебры. + С другой же стороны, определения данных понятий оказываются весьма вариативными и часто вызывают дискуссии. + Например, интересный анализ тонкостей определения группы можно найти в первом и втором параграфах первого раздела книги Николая Александровича Вавилова \enquote{Конкретная теория групп}~\cite{VavilovGroups}. + Мы же дадим определения, удобные для дальнейшего изложения материала. +} + +\section{Бинарные операции и их свойства} + +Введём понятие \emph{бинарной операции} и рассмотрим некоторые её свойства, такие как \emph{коммутативность} и \emph{ассоциативность}. + +\begin{definition}[Функция] + \emph{Функцией} будем называть бинарное отношение на двух множествах $S$ и $T$, такое, что каждому элементу из $S$ сопоставляется ровно один элемент из $T$. + Запись $f: S \to T$ как раз и обозначает, что функция $f$ сопоставляет элементы из $S$ элементам из $T$. +\end{definition} + +\begin{definition}[Домен функции] + Для функции $f: S \to T$, множество $S$ называется \emph{областью определения функции} или \emph{доменом функции}. +\end{definition} + +\begin{definition}[Кодомен функции] + Для функции $f: S \to T$, множество $T$ называется \emph{областью значений функции} или \emph{кодоменом функции}. +\end{definition} + +\begin{definition}[Двухместная функция] + Функцию, принимающую два аргумента, $f: R \times S \to T$ будем называть \emph{двухместной} или \emph{функцией арности два}. + Для записи таких функций будем использовать типичную нотацию: $t = f(r, s)$. +\end{definition} + +\begin{definition}[Бинарная операция] + \emph{Бинарная операция}~--- это двухместная функция, от которой дополнительно требуется, чтобы оба аргумента и результат лежали в одном и том же множестве: $f: S \times S \to S$. + В таком случае говорят, что бинарная операция определена на некотором множестве $S$. Для обозначения произвольной бинарной операции будем использовать символ $\circ$ и пользоваться инфиксной нотацией для записи: $s_3 = s_1 \circ s_2$. +\end{definition} + +\begin{definition}[Внешняя бинарная операция] + \emph{Внешняя бинарная операция}~--- это бинарная операция, у которой аргументы лежат в разных множествах, при этом результат~--- в одном из этих множеств. + Иными словами $\circ: R \times S \to S$, где $R$ может не совпадать с $S$~--- внешняя бинарная операция. +\end{definition} + +Необходимо помнить, что как функции, так и бинарные операции, могут быть частично определёнными (частичные функции, частичные бинарные операции). +Типичным примером частично определённой бинарной операции является деление на целых числах: она не определена, если второй аргумент равен нулю. + +Бинарные операции могут обладать некоторыми дополнительными свойствами, такими как \emph{коммутативность} или \emph{ассоциативность}, позволяющими преобразовывать выражения, составленные с использованием этих операций. + +\begin{definition}[Коммутативная операция] + Бинарная операция $\circ : S \times S \to S$ называется \emph{коммутативной}, если для любых $s_1, s_2 \in S$ верно, что $s_1 \circ s_2 = s_2 \circ s_1$. +\end{definition} + +\begin{example} + Рассмотрим несколько примеров коммутативных и некоммутативных операций. + \begin{itemize} + \item Операция сложения на целых числах является коммутативной: известный ещё со школы перестановочный закон сложения. + \item Операция умножения на целых числах является коммутативной: известный ещё со школы перестановочный закон умножения. + \item Операция конкатенации на строках\marginnote{TODO: Здесь слова о том, что из текста далее будет понятно, почему именно точка} $\cdot$ не является коммутативной: + \["ab" \cdot "c" = "abc" \neq "cab" = "c" \cdot "ab".\] + \item Операция умножения матриц (над целыми числами) $\cdot$ не является коммутативной: + \[\begin{pmatrix} + 1 & 1 \\ + 0 & 0 + \end{pmatrix} + \cdot + \begin{pmatrix} + 0 & 0 \\ + 1 & 1 + \end{pmatrix} + = + \begin{pmatrix} + 1 & 1 \\ + 0 & 0 + \end{pmatrix} + \neq + \begin{pmatrix} + 0 & 0 \\ + 1 & 1 + \end{pmatrix} + = + \begin{pmatrix} + 0 & 0 \\ + 1 & 1 + \end{pmatrix} + \cdot + \begin{pmatrix} + 1 & 1 \\ + 0 & 0 + \end{pmatrix} + .\] + \end{itemize} +\end{example} + +\begin{definition}[Ассоциативная бинарная операция] + Бинарная операция $\circ: S \times S \to S$ называется \emph{ассоциативной}, если для любых $s_1, s_2, s_3 \in S$ верно, что $(s_1 \circ s_2) \circ s_3 = s_1 \circ (s_2 \circ s_3)$. + Иными словами, для ассоциативной операции результат вычислений не зависит от порядка применения операций. +\end{definition} + +\begin{example} Рассмотрим несколько примеров ассоциативных и неассоциативных операций. + \begin{itemize} + \item Операция сложения на целых числах является ассоциативной. + \item Операция умножения на целых числах является ассоциативной. + \item Операция конкатенации на строках $\cdot$ является ассоциативной: + \[("a" \cdot "b") \cdot "c" = "a" \cdot ("b" \cdot "c") = "abc".\] + \item Операция возведения в степень (над целыми числами) $\hat{\mkern6mu}$ не является ассоциативной: + \marginnote{TODO: Мне не нравится этот символ. Может убрать обозначения из текста выше, а в формуле нарисовать башенку?} + \[(2\hat{\mkern6mu}2)\hat{\mkern6mu}3 = 4 \hat{\mkern6mu} 3 = 64 \neq 256 = 2 \hat{\mkern6mu} 8 = 2\hat{\mkern6mu}(2\hat{\mkern6mu}3).\] + \end{itemize} +\end{example} + +\begin{definition}[Дистрибутивная бинарная операция] + Говорят, что бинарная операция $\otimes: S \times S \to S$ является \emph{дистрибутивной} относительно бинарной операции $\oplus: S \times S \to S$, если + \begin{enumerate} + \item Для любых $s_1, s_2, s_3 \in S$, $s_1 \otimes (s_2 \oplus s_3) = (s_1 \otimes s_2) \oplus (s_1 \otimes s_3)$ (дистрибутивность слева). + \item Для любых $s_1, s_2 ,s_3 \in S$, $(s_2 \oplus s_3) \otimes s_1 = (s_2 \otimes s_1) \oplus (s_3 \otimes s_1)$ (дистрибутивность справа). + \end{enumerate} + Если операция $\otimes$ является коммутативной, то дистрибутивность слева и справа равносильны. +\end{definition} + +\begin{example} + Рассмотрим несколько примеров дистрибутивных операций. + \begin{itemize} + \item Умножение целых чисел дистрибутивно относительно сложения и вычитания: классический \emph{распределительный закон}, знакомый всем со школы. + \item Операция деления (допустим, на действительных числах) не коммутативна. + При этом, она дистрибутивна справа относительно сложения и вычитания, но не дистрибутивна слева% + \sidenote{ + Здесь может быть уместно вспомнить правила сложения дробей. + Дроби с общим знаминателем складывать проще как раз из-за дистрибутивности справа.}. + Так, $(a + b) / c = (a / c) + (b / c)$, но $c / (a + b) \neq (c / a) + (c / b)$. + \end{itemize} +\end{example} + +\begin{definition}[Идемпотентная бинарная операция] + Бинарная операция $\circ: S \times S \to S$ называется \emph{идемпотентной}, если для любого $s \in S$ верно, что $s \circ s = s$. +\end{definition} + +\begin{example} + Рассмотрим несколько примеров идемпотентных операций. + \begin{itemize} + \item Операция объединения множеств $\cup$ является идемпотентной: для любого множества $S$ верно, что $S \cup S = S$. + \item Операция сложения на целых числах не является идемпотентной. + \item Операции \enquote{логическое и} $\land$ и \enquote{логическое или} $\lor$ являются идемпотентными. + \item Операция \enquote{исключающее или} (\textsf{XOR}) не является идемпотентной. + \end{itemize} +\end{example} + +\begin{definition}[Нейтральный элемент] + Пусть есть коммутативная бинарная операция $\circ$ на множестве $S$. + Говорят, что $e \in S$ является \emph{нейтральным элементом} по операции $\circ$, если для любого $s \in S$ верно, что $e \circ s = s \circ e = s$. + Если бинарная операция не является коммутативной, то можно определить \emph{нейтральный слева} и \emph{нейтральный справа} элементы по аналогии. +\end{definition} + +\section{Полугруппа} + +\begin{definition}[Полугруппа] + Множество $S$ с заданной на нём ассоциативной бинарной операцией $\cdot: S \times S \to S$ называется \emph{полугруппой} и обозначается $(S, \cdot)$. + Если операция $\cdot$ является коммутативной, то говорят о \emph{коммутативной полугруппе}. +\end{definition} + +\begin{example} + Приведём несколько примеров полугрупп. + \begin{itemize} + \item Множество положительных целых чисел с операцией сложения является коммутативной полугруппой. + \item Множество целых чисел с операцией взятия наибольшего из двух ($\max$) является коммутативной полугруппой. + \item Множество всех строк конечной длины без пустой строки% + \sidenote{ + Множество всех строк конечной длины c пустой строкой также является полугруппой. + Однако, такая структура является ещё и моноидом, что будет показано далее.} + над фиксированным алфавитом $\Sigma$ с операцией конкатенации является полугруппой. + Так как конкатенация на строках не является коммутативной операцией, то и полугруппа не является коммутативной. + \end{itemize} +\end{example} + +\section{Моноид} + +\begin{definition}[Моноид] + \emph{Моноидом} называется полугруппа с нейтральным элементом. + Если операция является коммутативной, то можно говорить о \emph{коммутативном моноиде}. +\end{definition} + +\begin{example} + Приведём примеры моноидов, построенных на основе полугрупп из предыдущего раздела. + \begin{itemize} + \item Неотрицательные целые числа (или же натуральные числа с нулём) с операцией сложения являются моноидом. + Нейтральный элемент~--- $0$. + \item Целые числа, дополненные значением $-\infty$ (\enquote{минус бесконечность}) с операцией взятия наибольшего из двух ($\max$) являются моноидом. + Нейтральный элемент~--- $-\infty$. + \item Множество всех строк конечной длины с пустой строкой (строка длины 0) над фиксированным алфавитом $\Sigma$ и операцией конкатенации является моноидом. + Нейтральный элемент~--- пустая строка. + \item Квадратные неотрицательные матрицы% + \sidenote{Неотрицательной называется матрица, все элементы которой не меньше нуля.} фиксированного размера с операцией умножения задают моноид. + Нейтральный элемент~--- единичная матрица. + \end{itemize} +\end{example} + +\section{Группа} + +\begin{definition}[Группа] + Непустое% + \sidenote{Требование непустоты здесь, как и далее, в определениях полукольца и кольца~--- дискуссионный вопрос.} + множество $G$ с заданной на нём бинарной операцией $\circ: {G} \times {G} \to {G}$ называется \emph{группой} $(G ,\circ)$, если выполнены следующие аксиомы: + \begin{enumerate} + \item ассоциативность: для любых $a, b, c \in G$ выполнено $(a \circ b) \circ c = a \circ (b \circ c)$; + \item наличие нейтрального элемента $e$: для любого $a \in G$ выполнено $e \circ a = a \circ e = a$; + \item наличие обратного элемента: для любого $a \in G$ существует $a^{-1} \in G$, такой что $a \circ a^{-1} = a^{-1} \circ a = e$. + \end{enumerate} + Иными словами, группа~--- это моноид с дополнительным требованием наличия обратных элементов. +\end{definition} + +\begin{definition}[Абелева группа] + Если операция $\circ$ коммутативна, то говорят, что группа \emph{абелева}. +\end{definition} + +\begin{example} + Рассмотрим несколько примеров групп. + \begin{itemize} + \item Целые числа $\Z$ с операцией сложения $+$ являются группой. + Получается дополнением моноида из предыдущего раздела обратными по сложению элементами. + \item Целые числа $\Z$ без нуля% + \sidenote{ + При наличии нуля возникают трудности с нейтральным элементом. + Логично считать $1$ нейтральным по умножению, однако $0 \cdot 1 = 0$, а не 1, как того требует определение.} + с операцией умножения $\cdot$ не являются группой, так как нет обратных по умножению. + Действительно, возьмём $a = 3$, тогда должен существовать $a^{-1} \in \Z$, такой что $3 \cdot a^{-1} = 1$. + Видим, что $a^{-1} = 1/3$, но $1/3 \notin \Z$. + \item Множество обратимых% + \sidenote{ + Квадратная матрица $M$ называется обратимой, если существует матрица $N$, называемая обратной, такая что $M \cdot N = N \cdot M = I$, где $I$~--- единичная матрица. + К сожалению, не все матрицы являются обратимыми, потому, чтобы сконструировать группу, нам приходится требовать обратимость явно.} + матриц с операцией матричного умножения задают группу. + \end{itemize} +\end{example} + +\section{Полукольцо} + +\begin{definition}[Полукольцо] + Непустое множество $R$ с двумя бинарными операциями $\oplus: R \times R \to R$ (часто называют сложением) и $\otimes: R \times R \to R$ (часто называют умножением) называется \emph{полукольцом}, если выполнены следующие условия. + \begin{enumerate} + \item $(R, \oplus)$~--- это коммутативный моноид, нейтральный элемент которого~--- $\bz$. Для любых $a, b, c \in R$: + \begin{itemize} + \item $(a \oplus b) \oplus c = a \oplus (b \oplus c)$ + \item $\bz \oplus a = a \oplus \bz = a$ + \item $a \oplus b = b \oplus a$ + \end{itemize} + \item $(R, \otimes)$~--- это моноид, нейтральный элемент которого~--- $\bo$. Для любых $a, b, c \in R$: + \begin{itemize} + \item $(a \otimes b) \otimes c = a \otimes (b \otimes c)$ + \item $\bo \otimes a = a \otimes \bo = a$ + \end{itemize} + \item $\otimes$ дистрибутивно слева и справа относительно $\oplus$: + \begin{itemize} + \item $a \otimes (b \oplus c) = (a \otimes b) \oplus (a \otimes c)$ + \item $(a \oplus b) \otimes c = (a \otimes c) \oplus (b \otimes c)$ + \end{itemize} + \item $\bz$ является \emph{аннигилятором} по умножению: + \begin{itemize} + \item для любых $a \in R$ выполнено $\bz \otimes a = a \otimes \bz = \bz$ + \end{itemize} + \end{enumerate} + Если операция $\otimes$ коммутативна, то говорят о \emph{коммутативном полукольце}. + Если операция $\oplus$ идемпотентна, то говорят об \emph{идемпотентном полукольце}. +\end{definition} + +\begin{example} + \label{exmpl:semiring} + Рассмотрим пример полукольца, а заодно покажем, что левая и правая дистрибутивность могут существовать независимо для некоммутативного умножения% + \sidenote{ + Хороший пример того, почему левую и правую дистрибутивность в случае некоммутативного умножения нужно проверять независимо (правда, для колец), приведён Николаем Александровичем Вавиловым в книге \enquote{Конкретная теория колец} на странице 6~\cite{VavilovRings}.}% + . + + В качестве $R$ возьмём множество множеств строк конечной длины над некоторым алфавитом $\Sigma$. + В качестве сложения возьмём теоретико-множественное объединение: $\oplus \equiv \cup$. + Нейтральный элемент по сложению~--- это пустое множество ($\varnothing$). + В качестве умножения возьмём конкатенацию множеств ($\otimes \equiv \odot$) и определим её следующим образом: + \[S_1 \odot S_2 = \left\{ w_1 \cdot w_2 \mid w_1 \in S_1, w_2 \in S_2\right\},\] + где $\cdot$~--- конкатенация строк. + Нейтральным элементом по умножению будет являться множество из пустой строки: $\{\varepsilon\}$, где $\varepsilon$~--- обозначение для пустой строки. + + Проверим, что $(R, \cup, \odot)$ действительно полукольцо по нашему определению. + \begin{enumerate} + \item $(R, \cup)$~--- действительно коммутативный моноид с нейтральным элементом $\varnothing$. + Для любых $a, b, c \in R$ по свойствам теоретико-множественного объединения верно: + \begin{itemize} + \item $(a \cup b) \cup c = a \cup (b \cup c)$ + \item $\varnothing \cup a = a \cup \varnothing = a$ + \item $a \cup b = b \cup a$. + \end{itemize} + \item $(R, \odot)$~--- действительно моноид с нейтральным элементом $\{\varepsilon\}$. + Для любых $a, b, c \in R$: + \begin{itemize} + \item $(a \odot b) \odot c = a \odot (b \odot c)$ по определению $\odot$ + \item $\{\varepsilon\} \odot a = \{\varepsilon \cdot w \mid w \in a \} = \{w \mid w \in a \} = a \odot \{\varepsilon\} = a$ + \end{itemize} + Вообще говоря, сконструированный нами моноид не является коммутативным: легко проверить, например, что существуют непустые $a, b \in R$, $a \neq b$, $a \neq \{\varepsilon\}$, $b \neq \{\varepsilon\}$, такие что $a \cdot b \neq b \cdot a$ по причине некоммутативности конкатенации строк. + \item $\odot$ дистрибутивно слева и справа относительно $\cup$: + \begin{itemize} + \item Сначала проверим дистрибутивность слева. + \begin{align*} + a \odot (b \cup c) & = \{ w_1 \cdot w_2 \mid w_1 \in a, w_2 \in b \cup c\} \\ + & = \{ w_1 \cdot w_2 \mid w_1 \in a, w_2 \in b \} \cup \{ w_1 \cdot w_2 \mid w_1 \in a, w_2 \in c \} \\ + & = (a \odot b) \cup (a \odot c) + \end{align*} + \item Аналогично, $(a \cup b) \odot c = (a \odot c) \cup (b \odot c)$ + \end{itemize} + При этом, в общем случае, $a \odot (b \cup c) \neq (b \cup c) \odot a$ из-за некоммутативности операции $\odot$. + Действительно, + \begin{gather*} + \{"a"\} \odot (\{"b"\} \cup \{"c"\}) = \{"a"\} \odot \{"b","c" \} = \{"ab","ac" \} \\ + (\{"b"\} \cup \{"c"\}) \odot \{"a"\} = \{"b", "c"\} \odot \{"a"\} = \{"ba","ca"\} \\ + \{"ab","ac"\} \neq \{"ba","ca"\} + \end{gather*} + \item $\varnothing$ является \emph{аннигилятором} по умножению: для любого $a \in R$ верно, что + $\varnothing \odot a = \{ w_1 \cdot w_2 \mid w_1 \in \varnothing, w_2 \in a \} = \{ w_1 \cdot w_2 \mid w_1 \in a, w_2 \in \varnothing \} = a \odot \varnothing = \varnothing$ + \end{enumerate} +\end{example} + +\section{Кольцо} + +\begin{definition}[Кольцо] + Непустое множество $R$ с двумя бинарными операциями $\oplus: R \times R \to R$ (умножение) и $\otimes: R \times R \to R$ (сложение) называется \emph{кольцом}, если выполнены следующие условия. + \begin{enumerate} + \item $(R, \oplus)$~--- это абелева группа, нейтральный элемент которой~--- $\bz$. + Для любых $a, b, c \in R$: + \begin{itemize} + \item $(a \oplus b) \oplus c = a \oplus (b \oplus c)$ + \item $\bz \oplus a = a \oplus \bz = a$ + \item $a \oplus b = b \oplus a$ + \item для любого $a \in R$ существует $-a \in R$, такой что $a + (-a) = \bz$. + \end{itemize} + В последнем пункте кроется отличие от полукольца. + \item $(R, \otimes)$~--- это моноид, нейтральный элемент которого~--- $\bo$. + Для любых $a, b, c \in R$: + \begin{itemize} + \item $(a \otimes b) \otimes c = a \otimes (b \otimes c)$ + \item $\bo \otimes a = a \otimes \bo = a$ + \end{itemize} + \item $\otimes$ дистрибутивно слева и справа относительно $\oplus$: + \begin{itemize} + \item $a \otimes (b \oplus c) = (a \otimes b) \oplus (a \otimes c)$ + \item $(a \oplus b) \otimes c = (a \otimes c) \oplus (b \otimes c)$ + \end{itemize} + \end{enumerate} +\end{definition} + +Заметим, что мультипликативное свойство $\bz$ (быть аннигилятором по умножению) не указыватеся явно, так как может быть выведено из остальных утверждений. +Действительно, +\begin{enumerate} + \item $a \otimes \bz = a \otimes (\bz \oplus \bz)$, так как $\bz$~--- нейтральный по сложению, то $\bz \oplus \bz = \bz$ + \item Воспользуемся дистрибутивностью: $a \otimes (\bz \oplus \bz) = a \otimes \bz \oplus a \otimes \bz$. + В итоге: $a \otimes \bz = a \otimes \bz \oplus a \otimes \bz$ + \item Так как у нас есть группа по сложению, то для любого $a$ существует обратный элемент $a^{-1}$, $a \oplus a^{-1} = \bz$. + Прибавим $a^{-1} \otimes \bz$ к левой и правой части равенства% + \sidenote{Обычно данное действие воспринимается как очевидное, но, строго говоря, оно требует аккуратного введения структур с равенством и соответствующих аксиом.}% + , полученного на предыдущем шаге: + \[a \otimes \bz \oplus a^{-1} \otimes \bz = a \otimes \bz \oplus a \otimes \bz \oplus a^{-1} \otimes \bz.\] + \item Воспользуемся дистрибутивностью и ассоциативностью. + \begin{align*} + (a \oplus a^{-1}) \otimes \bz & = a \otimes \bz \oplus (a \oplus a^{-1}) \otimes \bz \\ + \bz \otimes \bz & = a \otimes \bz \oplus \bz \otimes \bz \\ + \bz & = a \otimes \bz + \end{align*} + \item Аналогично можно доказать, что $\bz = \bz \otimes a$. +\end{enumerate} + +%\section{Поле} + +\section{Матрицы и вектора} + +К определению матрицы мы подойдём структурно, так как в дальнейшем будем сопоставлять эту структуру с объектами различной природы, а значит определение матрицы через какой-либо из этих объектов (например через квадратичные формы) будет менее удобным. + +Договоримся, что \emph{алгебраическая структура}~--- это собирательное название для объектов вида \enquote{множество с набором операций} (например, кольцо, моноид, группа и т.д.), а соответствующее множество будем назвать \emph{носителем} этой структуры. + +\begin{definition}[Матрица] + Предположим, что у нас есть некоторая алгебраическая структура с носителем $S$. Тогда \emph{матрицей} будем называть прямоугольный массив размера $n \times m$, $n > 0$, $m > 0$, заполненный элементами из $S$. + + Говорят, что $n$~--- это высота матрицы или количество строк в ней, а $m$~--- ширина матрицы или количество столбцов. +\end{definition} + +При доступе к элементам матрицы используются их индексы. +При этом нумерация ведётся с левого верхнего угла, первым указывается строка, вторым~--- столбец. +В нашей работе мы будем использовать \enquote{программистскую} традицию и нумеровать строки и столбцы с нуля% +\sidenote{ + В противоположность \enquote{математической} традиции нумеровать строки и столбцы с единицы. + Стоит, правда, отметить, что в некоторых языках программирования (например, Fortran или COBOL) жива \enquote{математическая} традиция.}% +. + +\begin{example} + Пусть есть моноид $(S, \cdot)$, где $S$~--- множество строк конечной длины над алфавитом $\{a, b, c\}$. + Тогда можно построить, например, следующую матрицу $2 \times 3$. + \[ + M_{2 \times 3} = + \begin{pmatrix} + "a" & "ba" & "cb" \\ + "ac" & "bab" & "b" + \end{pmatrix} + \] + Для доступа к элементу матрицы будем использовать такую запись: $M_{2 \times 3}[1, 1] = "bab"$. +\end{example} + +К определению вектора мы также подойдём структурно. +\begin{definition}[Вектор] + \emph{Вектором} будем называть матрицу, хотя бы один из размеров которой равен единице. + Если единице равна высота матрицы, то это \emph{вектор-строка}, если же единице равна ширина матрицы, то это \emph{вектор-столбец}. +\end{definition} + +Операции над матрицами можно условно разделить на две группы: +\begin{itemize} + \item \emph{структурные}~--- не зависящие от алгебраической структуры, над которой строилась матрица, и работающие только с её структурой; + \item \emph{алгебраические}~--- определение таковых опирается на свойства алгебраической структуры, над которой построена матрица. +\end{itemize} + +\marginnote{TODO: Пример ниже чуток вылезает} +Примерами структурных операций является \emph{транспонирование}, \emph{взятие подматрицы} и \emph{взятие элемента по индексу}. + +\begin{marginfigure} + \[ + \begin{pmatrix} + "a" & "ba" & "cb" \\ + "ac" & "bab" & "b" + \end{pmatrix}^\top = + \begin{pmatrix} + "a" & "ac" \\ + "ba" & "bab" \\ + "cd" & "b" + \end{pmatrix} + \] + \caption{Пример транспонирования} +\end{marginfigure} +\begin{definition}[Транспонирование матрицы] + Пусть дана матрица $M_{n \times m}$. + Тогда результат её \emph{транспонирования}, это такая матрица $M'_{m \times n}$, что $M'[i,j] = M[j,i]$ для всех $0\leq i \leq m - 1$ и $0\leq j \leq n - 1$. + + Операцию транспонирования принято обозначать как $M^\top$. +\end{definition} + +\begin{definition}[Прямая сумма матриц] + \marginnote{TODO: Здесь точно большой плюс? + TODO: Я ниже заменил $..$ на $\dots$ может быть это не самая лучшая идея, хотя вроде дальше особо такое не используется. + У Виноградова в учебнике используется довольно прикольная как по мне нотация $[a : b] = \{x \mid a \leq x \leq b\}$, как раз для целочисленных интервалов. + TODO: "Рис" надо заменить на "Пример"} + Пусть даны матрицы $M_{n_1 \times m_1}$ и $N_{n_2 \times m_2}$. + Тогда \emph{прямой суммой} этих матриц называется матрица $L_{(n_1 + n_2) \times (m_1 + m_2)}$ вида + \[ + L = + \begin{pmatrix} + M & 0 \\ + 0 & N + \end{pmatrix} + \] + Где 0 обозначает нулевой блок. Прямая сумма обозначается $L = M \bigoplus N$. +\end{definition} + +\begin{marginfigure} + \begin{align*} + \begin{pmatrix} + "a" & "ba" & "cb" \\ + "ac" & "bab" & "b" + \end{pmatrix} & [0 \dots 1, 1 \dots 2] = \\ + ={} & \begin{pmatrix} + "ba" & "cb" \\ + "bab" & "b" + \end{pmatrix} + \end{align*} + \caption{Пример взятия подматрицы} +\end{marginfigure} +\begin{definition}[Взятие подматрицы] + Пусть дана матрица $M_{n\times m}$. + Тогда $M_{n \times m}[i_0 \dots i_1, j_0 \dots j_1]$~--- это такая $M'_{(i_1 - i_0 + 1) \times (j_1 - j_0 + 1)}$, что $M'[i, j] = M[i_0 + i, j_0 + j]$ для всех $0 \leq i \leq i_1 - i_0 + 1$ и $0 \leq j \leq j_1 - j_0 + 1$. +\end{definition} + +\begin{marginfigure} + \[ + \begin{pmatrix} + "a" & "ba" & "cb" \\ + "ac" & "bab" & "b" + \end{pmatrix}[0, 1] = "ba" + \] + \caption{Пример взятия элемента по индексу} +\end{marginfigure} +\begin{definition}[Взятие элемента по индексу] + \emph{Взятие элемента по индексу}~--- это частный случай взятия подматрицы, когда начало и конец\enquote{среза} совпадают: $M[i, j] = M[i \dots i, j\dots j]$ +\end{definition} + +Из алгебраических операций над матрицами нас в дальнейшем будут интересовать \emph{поэлементные операции}, \emph{скалярные операции}, \emph{матричное умножение}, \emph{произведение Кронекера}. + +\begin{definition}[Поэлементные операции] + Пусть $G = (S, \circ)$~--- полугруппа% + \sidenote[][*2]{Здесь, как и в дальнейшем, требование к структуре быть полугруппой не обязательно. + Оно лишь позволяет нам получить ассоциативность соответствующих операций над матрицами, что может оказаться полезным при дальнейшей работе.}% + , $M_{n \times m}$, $N_{n \times m}$~--- две матрицы одинакового размера над этой полугруппой. + Тогда $\mathrm{ewise}(M, N, \circ) = P_{n \times m}$, такая, что $P[i, j] = M[i, j] \circ N[i, j]$. +\end{definition} + +\begin{example} + Пусть $G$~--- полугруппа строк с конкатенацией $\cdot$, + \[M = + \begin{pmatrix} + "a" & "ba" & "cb" \\ + "ac" & "bab" & "b" + \end{pmatrix}, + \qquad + N = + \begin{pmatrix} + "c" & "aa" & "b" \\ + "a" & "bac" & "bb" + \end{pmatrix}. + \] + Тогда + \[ + \mathrm{ewise}(M, N, \cdot) = + \begin{pmatrix} + "ac" & "baaa" & "cbb" \\ + "aca" & "babbac" & "bbb" + \end{pmatrix}. + \] +\end{example} + +\begin{definition}[Скалярная операция] + Пусть $G = (S, \circ)$~--- полугруппа, $M_{n \times m}$~--- матрица над этой полугруппой, $x \in S$. + Тогда $\mathrm{scalar}(M, x,\circ) = P_{n \times m}$, такая, что $P[i, j] = M[i, j] \circ x$, а $\mathrm{scalar}(x, M, \circ) = P_{n \times m}$, такая, что $P[i, j] = x \circ M[i, j]$. +\end{definition} + +\begin{example} + Пусть $G$~--- полугруппа строк с конкатенацией $\cdot$, $x = "c"$, + \[ + M = + \begin{pmatrix} + "a" & "ba" & "cb" \\ + "ac" & "bab" & "b" + \end{pmatrix}. + \] + Тогда + \begin{gather*} + \mathrm{scalar}(M,x, \cdot) = + \begin{pmatrix} + "ac" & "bac" & "cbc" \\ + "acc" & "babc" & "bc" + \end{pmatrix},\\ + \mathrm{scalar}(x, M, \cdot) = + \begin{pmatrix} + "ca" & "cba" & "ccb" \\ + "cac" & "cbab" & "cb" + \end{pmatrix}. + \end{gather*} +\end{example} + +\begin{definition}[Матричное умножение] + \label{def:MxM} + Пусть $G = (S, \oplus, \otimes)$~--- полукольцо, $M_{n \times m}$, $N_{m\times k}$~--- две матрицы над этим полукольцом. + Тогда $M \cdot N = P_{n \times k}$, такая, что $P[i, j] = \bigoplus_{0 \leq l < m} M[i, l] \otimes N[l, j]$. +\end{definition} + +\begin{example} + Пусть $G$~--- полукольцо из примера~\ref{exmpl:semiring}, + \[ + M = + \begin{pmatrix} + \{"a"\} & \{"a"\} \\ + \{"b"\} & \{"b"\} + \end{pmatrix}, + \qquad + N = + \begin{pmatrix} + \{"c"\} \\ + \{"d"\} + \end{pmatrix}. + \] + Тогда + \[ + M \cdot N = + \begin{pmatrix} + \{"a" \cdot "c"\} \cup \{"a" \cdot "d"\} \\ + \{"b" \cdot "c"\} \cup \{"b" \cdot "d"\} + \end{pmatrix}= + \begin{pmatrix} + \{"ac" \ , "ad"\} \\ + \{"bc" \ , "bd"\} + \end{pmatrix}. + \] +\end{example} + + +\begin{definition}[Произведение Кронекера] + Пусть $G = (S, \circ)$~--- полугруппа, $M_{m \times n}$ и $N_{p \times q}$~--- две матрицы над этой полугруппой. + Тогда произведение Кронекера или тензорное произведение матриц $M$ и $N$~--- это блочная матрица $C$ размера $mp \times nq$, вычисляемая следующим образом: + \[ + C = A \otimes B = + \begin{pmatrix} + \mathrm{scalar}(M[0,0],N,\circ) & \cdots & \mathrm{scalar}(M[0,n-1],N,\circ) \\ + \vdots & \ddots & \vdots \\ + \mathrm{scalar}(M[m-1,0],N,\circ) & \cdots & \mathrm{scalar}(M[m-1,n-1],N,\circ) + \end{pmatrix} + \] + \marginnote{TODO: Здесь вылезло} +\end{definition} + +\begin{remark} + \label{note:KronIsNotCommutative} + Произведение Кронекера не является коммутативным. + При этом всегда существуют две матрицы перестановок $P$ и $Q$ такие, что $A \otimes B = P(B \otimes A)Q$. +\end{remark} + +\newcommand{\examplemtrx} +{ + \begin{pmatrix} + 5 & 6 & 7 & 8 \\ + 9 & 10 & 11 & 12 \\ + 13 & 14 & 15 & 16 + \end{pmatrix} +} + +\begin{example} + Возьмём в качестве полугруппы целые числа с умножением. + \[ + M= + \begin{pmatrix} + 1 & 2 \\ + 3 & 4 + \end{pmatrix}, + \qquad + N=\examplemtrx + \] + Тогда + \begin{align*} + M \otimes N & = + \begin{pmatrix} + 1 & 2 \\ + 3 & 4 + \end{pmatrix} + \otimes + \examplemtrx = \\ + & = + \begin{pNiceArray}[margin]{c|c} + 1 \examplemtrx & 2 \examplemtrx \\ + \midrule + 3 \examplemtrx & 4 \examplemtrx + \end{pNiceArray} = \\ + & = + \begin{pNiceArray}[margin]{cccc|cccc} + 5 & 6 & 7 & 8 & 10 & 12 & 14 & 16 \\ + 9 & 10 & 11 & 12 & 18 & 20 & 22 & 24 \\ + 13 & 14 & 15 & 16 & 26 & 28 & 30 & 32 \\ + \midrule + 15 & 18 & 21 & 24 & 20 & 24 & 28 & 32 \\ + 27 & 30 & 33 & 36 & 36 & 40 & 44 & 48 \\ + 39 & 42 & 45 & 48 & 52 & 56 & 60 & 64 + \end{pNiceArray} + \end{align*} +\end{example} + +\section{Теоретическая сложность умножения матриц} + +В рамках такого раздела теории сложности, как мелкозернистая сложность (fine-grained complexity) задача умножения двух матриц оказалась достаточно важной, так как через вычислительную сложность этой задачи можно оценить сложность большого класса различных задач. +С примерами таких задач можно ознакомиться в работе~\sidecite{Williams:2010:SEP:1917827.1918339}. Поэтому рассмотрим алгоритмы нахождения произведения двух матриц более подробно. +Далее для простоты мы будем предполагать, что перемножаются две квадратные матрицы одинакового размера $n \times n$. + +Для начала построим наивный алгоритм, сконструированный на основе определения произведения матриц. +Такой алгоритм представлен на листинге~\ref{algo:MxM}. +\marginnote{TODO: Ничего против не имею, но точно ли название "Листинг" здесь хорошо? + TODO: Оформление алгоритмов точно надо обсудить, потому что я в этом мало понимаю.} +Его работу можно описать следующим образом: для каждой строки в первой матрице и для каждого столбца в второй матрице найти сумму произведений соответствующих элементов. +Данная сумма будет значением соответствующей ячейки результирующей матрицы. +\begin{algorithm} + \caption{Наивное перемножение матриц} + \label{algo:MxM} + + \DontPrintSemicolon + \SetAlgoNoLine + \SetAlgoNoEnd + + \SetKwProg{KwFn}{function}{}{} + \SetKwFunction{FMatrixMult}{MatrixMult} + + \KwFn{\FMatrixMult{$M_1$, $M_2$, $G = (S, \oplus, \otimes)$}}{ + $M_3 =$ empty matrix of size $n \times n$\; + \For{$i \in 0 \dots n-1$}{ + \For{$j \in 0 \dots n-1$}{ + \For{$k \in 0 \dots n-1$}{ + $M_3[i, j] = M_3[i, j] \oplus ( M_1[i, k] \otimes M_2[k, j])$ + } + } + } + \KwRet{$M_3$} + } +\end{algorithm} + +Сложность наивного произведения двух матриц составляет $O(n^3)$ из-за тройного вложенного цикла, где каждый уровень вложенности привносит $n$ итераций. +Но можно ли улучшить этот алгоритм? +Первый положительный ответ был опубликовал Ф. Штрассен в 1969 году~\sidecite{Strassen1969}. +Сложность предложенного им алгоритма~--- $O(n^{\log_2 7}) \approx O(n^{2.81})$. +Основная идея~--- рекурсивное разбиение исходных матриц на блоки и вычисление их произведения с помощью только 7 умножений, а не 8. + +Рассмотрим алгоритм Штрассена более подробно. +Пусть $A$ и $B$~--- две квадратные матрицы размера $2^n \times 2^n$ над кольцом $R=(S, \oplus, \otimes)$. +Если размер умножаемых матриц не является натуральной степенью двойки, то дополняем исходные матрицы дополнительными нулевыми строками и столбцами. +Наша задача найти матрицу $C = A \cdot B$. +\marginnote{TODO: Только здесь заметил, а не хотим ли мы красную строку, всё-таки в России живем?} + +Разделим матрицы $A, B$ и $C$ на четыре равные по размеру блока. +\[ + A = + \begin{pmatrix} + A_{1,1} & A_{1,2} \\ + A_{2,1} & A_{2,2} + \end{pmatrix}, + \quad + B = + \begin{pmatrix} + B_{1,1} & B_{1,2} \\ + B_{2,1} & B_{2,2} + \end{pmatrix}, + \quad + C = + \begin{pmatrix} + C_{1,1} & C_{1,2} \\ + C_{2,1} & C_{2,2} + \end{pmatrix} +\] + +По определению произведения матриц выполняются следующие равенства. +\marginnote{TODO: Вообще можно попробовать раскидать на 2 столбца} +\begin{align*} + C_{1, 1} & = A_{1, 1} \cdot B_{1, 1} + A_{1, 2} \cdot B_{2, 1} \\ + C_{1, 2} & = A_{1, 1} \cdot B_{1, 2} + A_{1, 2} \cdot B_{2, 2} \\ + C_{2, 1} & = A_{2, 1} \cdot B_{1, 1} + A_{2, 2} \cdot B_{2, 1} \\ + C_{2, 2} & = A_{2, 1} \cdot B_{1, 2} + A_{2, 2} \cdot B_{2, 2} +\end{align*} + +Данная процедура не даёт нам ничего нового с точки зрения вычислительной сложности. +Но мы можем двинуться дальше и определить следующие элементы. +\begin{align*} + P_1 & \equiv (A_{1, 1} + A_{2, 2}) \cdot (B_{1, 1} + B_{2, 2}) \\ + P_2 & \equiv (A_{2, 1} + A_{2, 2}) \cdot B_{1, 1} \\ + P_3 & \equiv A_{1, 1} \cdot (B_{1, 2} - B_{2, 2}) \\ + P_4 & \equiv A_{2, 2} \cdot (B_{2, 1} - B_{1, 1}) \\ + P_5 & \equiv (A_{1, 1} + A_{1, 2}) \cdot B_{2, 2} \\ + P_6 & \equiv (A_{2, 1} - A_{1, 1}) \cdot (B_{1, 1} + B_{1, 2}) \\ + P_7 & \equiv (A_{1, 2} - A_{2, 2}) \cdot (B_{2, 1} + B_{2, 2}) +\end{align*} + +Используя эти элементы мы можем выразить блоки результирующей матрицы следующим образом. +\begin{align*} + C_{1, 1} & = P_1 + P_4 - P_5 + P_7 \\ + C_{1, 2} & = P_3 + P_5 \\ + C_{2, 1} & = P_2 + P_4 \\ + C_{2, 2} & = P_1 - P_2 + P_3 + P_6 +\end{align*} + +При таком способе вычисления мы получаем на одно умножение подматриц меньше, чем при наивном подходе. +Это и приводит, в конечном итоге, к улучшению сложности всего алгоритма, который основывается на рекурсивном повторении проделанной выше процедуры. + +\marginnote{TODO: здесь \textbackslash{}sidecite не влезает} +Впоследствии сложность постепенно понижалась в ряде работ, таких как~\cite{Pan1978,BiniCapoRoma1979,Schonhage1981,CoppWino1982,CoppWino1990}. +Было введено специальное обозначение для показателя степени в данной оценке: $\omega$. +То есть сложность умножения матриц~--- это $O(n^\omega)$, и задача сводится к уменьшению значения $\omega$. +В настоящее время работа над уменьшением показателя степени продолжается и сейчас уже предложены решения с $\omega < 2.373$% +\sidenote{ + В данной области достаточно регулярно появляются новые результаты, дающие сравнительно небольшие, в терминах абсолютных величин, изменения. + Так, в 2021 была представлена работа, улучшающая значение $\omega$ в пятом знаке после запятой~\cite{alman2020refined}. + Несмотря на кажущуюся несерьёзность результата, подобные работы имеют большое теоретическое значение, так как улучшают наше понимание исходной задачи и её свойств.}% +. + +Всё тем же Ф. Штрассеном ещё в 1969 году была выдвинута гипотеза о том, что для достаточно больших $n$ существует алгоритм, который для любого сколь угодно маленького наперёд заданного $\varepsilon$ перемножает матрицы за $O(n^{2+\varepsilon})$. +На текущий момент ни доказательства, ни опровержения этой гипотезы не предъявлено. + +Важной особенностью указанного выше направления улучшения алгоритмов является то, что оно допускает использования (и даже основывается на использовании) более богатых алгебраических структур, чем требуется для определения умножения двух матриц. +Так, уже алгоритм Штрасеена использует операцию вычитания, что приводит к необходимости иметь обратные элементы по сложению, а значит определять матрицы над кольцом. +Хотя для исходного определения (\ref{def:MxM}) достаточно более бедной структуры. +При этом, часто, структуры, возникающие в прикладных задачах кольцами не являются. +\marginnote{TODO: Не кажется ли что текста на полях слишком много и его можно прямо в главу вписать?} +Примерами могут служить тропическое (или $\{min, +\}$) полукольцо, играющее ключевую роль в тропической математике, или булево ($\{\lor, \land\}$) полукольцо, возникающее, например, при работе с отношениями% +\sidenote{ + Вообще говоря, в некоторых прикладных задачах возникают структуры, не являющиеся даже полукольцом. + Предположим, что есть три различных множества $S_1$, $S_2$ и $S_3$ и две двухместные функции $f: S_1 \times S_2 \to S_3$ и $g: S_3 \times S_3 \to S_3$. + Этого достаточно, чтобы определить произведение двух матриц $M_1$ и $M_2$, построенных из элементов множеств $S_1$ и $S_2$ соответственно. + Результирующая матрица будет состоять из элементов $S_3$. + Как видно, функции не являются бинарными операциями в смысле нашего определения. + Несмотря на кажущуюся экзотичность, подобные структуры возникают на практике при работе с графами и учитываются, например, в стандарте GraphBLAS (\url{https://graphblas.github.io/}), где, кстати, называются полукольцами, что выглядит не вполне корректно.}% +. +Значит, описанные выше решения не применимы и вопрос о существовании алгоритма с менее чем кубической сложностью снова актуален. + +В попытках ответить на этот вопрос появились так называемые комбинаторные алгоритмы умножения матриц% +\sidenote{ + В противовес описанным выше, не являющимся комбинаторными. + Стоит отметить, что строгое определение комбинаторных алгоритмов отсутствует, хотя этот термин и получил широкое употребление. + В частности, Н.~Бансал (Nikhil Bansal) и Р.~Уильямс (Ryan Williams) в работе~\cite{5438580} дают определение комбинаторного алгоритма, но тут же замечают следующее: \enquote{We would like to give a definition of \enquote{combinatorial algorithm}, but this appears elusive. Although the term has been used in many of the cited references, nothing in the literature resembles a definition. For the purposes of this paper, let us think of a \enquote{combinatorial algorithm} simply as one that does not call an oracle for ring matrix multiplication.}. + Ещё один вариант определения и его обсуждение можно найти в~\cite{das2018lower}.}% +. +Классический результат в данной области~--- это алгоритм четырёх русских, предложенный В. Л. Арлазаровым, Е. А. Диницем, М. А. Кронродом и И. А. Фараджевым в 1970 году~\cite{ArlDinKro70}, позволяющий перемножить матрицы над конечным полукольцом за $O(n^3/\log n)$. +Лучшим результатом% +\sidenote{ +В работе~\cite{das2018lower} предложен алгоритм со сложностью $\Omega(n^{7/3}/2^{O(\sqrt{\log n})})$, однако авторы утверждают, что сами не уверены в комбинаторности предложенного решения. +По-видимому, полученные результаты ещё должны быть проверены сообществом.} +в настоящее время является алгоритм со сложностью% +\sidenote{Нотация $\hat{O}$ скрывает $poly(\log\log)$ коэффициенты.} $\hat{O}(n^3/\log^4 n)$~\cite{10.1007/978-3-662-47672-7_89}. + +Как видим, особенности алгебраических структур накладывают серьёзные ограничения на возможности конструирования алгоритмов. +Отметим, что, хотя, в указанных случаях и предлагаются решения лучшие, чем наивное кубическое, они обладают принципиально разной асимптотической сложностью. +В первом случае сложность оценивается полиномом, степень которого меньше третьей. +Такие решения принято называть \emph{истинно субкубическими} (truly subcubic). +В то время как в случае комбинаторных алгоритмов степень полинома остается прежней, третьей, хотя сложность и уменьшается на логарифмический фактор. +Такие решения принято называть \emph{слегка субкубическими} (mildly subcubic). +Естественный вопрос о существовании истинно субкубического алгоритма перемножения матриц над полукольцами (или же комбинаторного перемножения матриц) всё ещё не решён% +\sidenote{Один из кандидатов~--- работа~\cite{das2018lower}, однако на текущий момент предложенное в ней решение требует проверки.}. + +%Заметим, что скалярная операция~--- это частный случай произвеления Кронекера: достаточно превратить элемент носителя полугруппы в матрицу размера $1\times 1$. + +%\section{Вопросы и задачи} +%\begin{enumerate} +% \item Привидите примеры некоммутативных операций. +% \item Привидите примеры ситуаций, когда наличие у бинарных операций каких-либо дополнитльных свойств (ассоциативности, коммутативности), позволяет строить более эффективные алгоритмы, чем в общем случае. +%\end{enumerate} diff --git a/tex/main.tex b/tex/main.tex index 2a0cf89..8c04316 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -7,17 +7,19 @@ \input{styles/language.tex} \input{styles/utils.tex} \input{styles/tikz.tex} +\input{styles/math.tex} +\input{styles/theorems.tex} -\usepackage{microtype} - -\usepackage{kaobiblio} +\usepackage{kaobiblio} % Обертка для biblatex, позволяет печатать сноску сбоку \addbibresource{FormalLanguageConstrainedReachabilityLectureNotes.bib} +\SetAlgorithmName{Листинг}{листинг}{Список листингов} + \tikzexternalize \title{О достижимости с ограничениями в терминах формальных языков} \author{Семён Григорьев} -\date{\today} +\date{\gitVer{}} \begin{document} @@ -30,10 +32,15 @@ \mainmatter \setchapterstyle{kao} -\setchapterpreamble[u]{\margintoc} \input{Introduction} +\pagelayout{wide} % No margins +\addpart{Необходимые вводные} +\pagelayout{margin} % Restore margins + +\input{LinearAlgebra} + \backmatter \setchapterstyle{plain} diff --git a/tex/styles/language.tex b/tex/styles/language.tex index 1133a38..6d6f733 100644 --- a/tex/styles/language.tex +++ b/tex/styles/language.tex @@ -1,3 +1,6 @@ \usepackage{polyglossia} % Локализация документа --- переносы и всё такое \setmainlanguage{russian} \setotherlanguage{english} + +\usepackage[autostyle]{csquotes} % Правильные кавычки в зависимости от языка +\usepackage{microtype} % Полезные типографические ништячки diff --git a/tex/styles/math.tex b/tex/styles/math.tex new file mode 100644 index 0000000..53c8cfb --- /dev/null +++ b/tex/styles/math.tex @@ -0,0 +1,8 @@ +\usepackage{amsmath, amsfonts, amssymb, amsthm, mathtools} % Advanced math tools. +\usepackage{nicematrix} + +% \setmathfont[range={\doubleplus}, Scale=MatchLowercase]{Asana Math} + +\NewDocumentCommand{\Z}{}{\mathbb{Z}} +\NewDocumentCommand{\bz}{}{\mathbb{0}} % Bold zero +\NewDocumentCommand{\bo}{}{\mathbb{1}} % Bold one diff --git a/tex/styles/theorems.tex b/tex/styles/theorems.tex new file mode 100644 index 0000000..3490597 --- /dev/null +++ b/tex/styles/theorems.tex @@ -0,0 +1,66 @@ + +\usepackage{thmtools} + +%%% theorem-like envs +\theoremstyle{definition} + +\declaretheoremstyle[spaceabove=0.5\topsep, + spacebelow=0.5\topsep, + headfont=\bfseries\sffamily, + bodyfont=\normalfont, + headpunct=., + postheadspace=5pt plus 1pt minus 1pt]{myStyle} +\declaretheoremstyle[spacebelow=\topsep, + headfont=\bfseries\sffamily, + bodyfont=\normalfont, + headpunct=., + postheadspace=5pt plus 1pt minus 1pt,]{myStyleWithFrame} +\declaretheoremstyle[spacebelow=\topsep, + headfont=\bfseries\sffamily, + bodyfont=\normalfont, + headpunct=., + postheadspace=5pt plus 1pt minus 1pt, + qed=\blacksquare]{myProofStyleWithFrame} + +\tcbuselibrary{breakable, skins} +\tcbset{shield externalize} +\tcbset{boxrule=0pt, + sharp corners, + borderline west={0.3mm}{0pt}{black}, + frame hidden, + enhanced, + interior hidden, + left=2mm, + top = 1mm, + bottom = 1mm, + right = 0.5mm +} + +% \tcolorboxenvironment{theorem}{} +% \tcolorboxenvironment{theorem*}{} +% \tcolorboxenvironment{axiom}{} +% \tcolorboxenvironment{assertion}{} +% \tcolorboxenvironment{lemma}{} +% \tcolorboxenvironment{proposition}{} +% \tcolorboxenvironment{corollary}{} +\tcolorboxenvironment{definition}{} +% \tcolorboxenvironment{proofReplace}{toprule=0mm,bottomrule=0mm,rightrule=0mm, colback=white, breakable } + +% \declaretheorem[name=Теорема, numberwithin=chapter, style=myStyleWithFrame]{theorem} +% \declaretheorem[name=Теорема, numbered=no, style=myStyleWithFrame]{theorem*} +% \declaretheorem[name=Аксиома, sibling=theorem, style=myStyleWithFrame]{axiom} +% \declaretheorem[name=Преположение, sibling=theorem, style=myStyleWithFrame]{assertion} +% \declaretheorem[name=Лемма, sibling=theorem, style=myStyleWithFrame]{lemma} +% \declaretheorem[name=Предложение, sibling=theorem, style=myStyleWithFrame]{proposition} +% \declaretheorem[name=Следствие, numberwithin=theorem, style=myStyleWithFrame]{corollary} + +\declaretheorem[name=Определение, numberwithin=chapter, style=myStyleWithFrame]{definition} +% \declaretheorem[name=Свойство, numberwithin=chapter, style=myStyle]{property} +% \declaretheorem[name=Свойства, numbered=no, style=myStyle]{propertylist} + +\declaretheorem[name=Пример, numberwithin=chapter, style=myStyle]{example} +\declaretheorem[name=Замечание, numbered=no, style=myStyle]{remark} + +% \declaretheorem[name=Доказательство, numbered=no, style=myProofStyleWithFrame]{proofReplace} +% \renewenvironment{proof}[1][\proofname]{\begin{proofReplace}}{\end{proofReplace}} +% \declaretheorem[name=Доказательство, numbered=no, style=myProofStyleWithFrame]{longProof} diff --git a/tex/styles/utils.tex b/tex/styles/utils.tex index 1541c1b..50610ad 100644 --- a/tex/styles/utils.tex +++ b/tex/styles/utils.tex @@ -1,3 +1,5 @@ \usepackage{xurl} % Разрешить переносить URL на любой букве +\usepackage{booktabs} +\usepackage[noheader]{gitver} \NewDocumentCommand{\email}{m}{\href{mailto:#1}{#1}} % Кликабельный email From 9c3f42d7f35ba2706850fd8812f64ca9fb9ab68e Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Wed, 12 Jun 2024 23:37:07 +0300 Subject: [PATCH 11/29] Add main.pdf to .gitignore --- .gitignore | 1 + tex/main.pdf | Bin 13399 -> 0 bytes 2 files changed, 1 insertion(+) delete mode 100644 tex/main.pdf diff --git a/.gitignore b/.gitignore index 8c7636a..5cd9a02 100644 --- a/.gitignore +++ b/.gitignore @@ -277,3 +277,4 @@ TSWLatexianTemp* tex/FormalLanguageConstrainedReachabilityLectureNotes.pdf tex/figures/externalized/* +tex/main.pdf diff --git a/tex/main.pdf b/tex/main.pdf deleted file mode 100644 index 482a5a7c91724ab5e0d0dd2d2e9d5e0709b93395..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13399 zcmch81yEhd5@>=32`(W7xHu%py~xEOxVyW%ySsak03o=$I|&d7?(S~EHMo4(WOwu4 z+uHx@SM5@qd(P>ZX*u09)ji!qD#a&24WeO$C+!>mGS)sd^tA(?0RRM8>X^W@vjb@5 zoUQZ$v`UgXCi=Q|09sjl9lPHk0+u%B0NTgj-+F)mv^+ePP5{-1p+Eo#_~TLs(28r@ z*%&{74DE~n zAVvTuC*b!#cw0LgeQk4ir8u33-r$!7u}<}|2>`1J(|EjV_kIg|E?sD%j7>K z3HaZY&F9ShJ z&FGz}wAxoBIq}~2`Mn_a10sPG^{@qYJOao@2Aozg9%8ol!9**%!5+i2;qsH$F--o3 z_%*E#6J0~k5X3i|%cC(xCOn);Y0COuYSoO*8A;vRFT6Ym{4&ort%CDiy#LLoyz}!_ z`*+}otR=B-KAE^k-V$8x?aJ3j`?`d^hvOx4wbQVUBgexRx z5N@Xs)|mJVu9BCE_k3ABqGzRsnZV_9esEtM7T1I=5~FT1!A4u|QnLV^gv85aQhSy3 zHJ-QE&Ste#@G&`x`f|Dp1RdLnk;}Ni5s$3@^#&P#HI~2o#2^OHUw-21@XzqAZ&CcN zT|?Y`>^&{cD*!%G6h^MeQznE>o;&^tJVEbO-1=Ht+@P2M%p_NI*NFRhs)>>A;U3!tYbz@1&#q)qVhf8j!9QqP12U z6N;9V7I4dS$>GTp$$kjizaaGMivCA9z$?rrU}<6Z7z+S-|K6FWV|bWHf4K91GEl8x zDu-_PQsR{jx2_p|vI4n7K#i9};e^U8j5_VJZ4<`VSfTMmKGH!LYgkalWMgUubR=GI zM&({ZfcO^-QX~{w(y9exCe?4H%e9A1YG>zVX&0vkIU3QCiPX<`x2A0!Jo+v-J~AC# zvmc!FeT*DDIaxirbUWU&(pQq3dLxRaBcHzoCyZnKMm`_zBbi_x*pS3R=(|6a9^@2u zADR!|pl)jXp^^@iDABG`voczi#tPHjWatoh;b6aX6ngN)$!+?@BFE{LrlW|)nnGrY zFoZiUVKg8msPJs%N{m?d`hamUfsT>N*;K)#b>rgHtFzEpR`Vm+d1lPG6#5f-DZJCo ztk-&ew~4%(%UdG>7dIP|nON;o{Eg=?`mPVI({W>TYv0p|?J>)M~J zg{W7!2LOgqrSDFfIoLHOWQ*Wh_tZ5GN^0uhcM_xZQwG?J^T=|y&!%$PT)gfbwI&CR7fZRs8)U$8f<5FC0mRFRPd5F| z9J|(h139gFi+APCJj*py`6jaD2E3W?3XHp9rTK(95|gMdG4K*bk-s5HqEjXt?CT+@ zRn#;MmDJyAEu;<)Ac65mWA)zemEK*n;J;3N4Hy!Y^IoWdz5gohm|w#9{eA7|qIy%< zvt;tOuo@|4?t3Nlc)^=n z@-O*k9hvjYOP@XLV7wi8^tij|kf7J0Xc;Px#W?f62~0TyaAdv6v_q$p8w1m9pjG`E zpS$=*snOwvXm=GJk{%(6-c6XW1UbuJr1ZSfB|3GfB-5lV(ci|2ynd$s2Ci?ADSqpu z-L&Xs0nYvMC!<9{Qho>BrZ~S+Ul>Gi%lnLp!o?@eC$(RFIpUlL%r9W58p`(3Tw>f) z`devA*pKME&!DJf1~im$X48rAW?2S=*_iJQf^?Y-1ueh&(g-X-4<_G=o^Op!$XD|@ zWj^^lt+p`lfF%gK)CUVvI&Dqd8F!_1l8ox__Mw$eEm94YO!$b`pFQ6O)=kC)9q^Zg zEF=n(#XXB-*mam#N|_UP}d+yq(;jnp~ARwjSp8|`%AKBLDsi!~>c9EaMA z>k0O5`I_6jtqT0K3s&2E647P65&}z9g(+{sPcQ@gW#0F(ZdTi80n7L1eak z+vvBJhV6sotMffPBSbvPk^S=5&>n<2FC)l?*vcv8!am`5=+3ty3C>k;<=5~xHTG{1 zezD^MV9CdC5)ez(6mR(ITT>QfXJMeJm3B5>zDgpMeYhuD0@{6wJdWk!>ZYNyl|Gi!uIpOArFbPIB&4Fk)x z4&^&*moWC~<1EByT+oxWnc^)3ZV_AQBc~HcCjQ2ATEQ|o{**N4IidvbgUVj+)vN1N zOQ?|fwyXkOB>Ix=j%6nT5q|G% zJI$zUV#~QDFy=jMr3z9fcP+PJ6|d(KR-Ptsvjdqmy{&A}NG7O$05WDKA10qOzR-1; z0vvvVS@7-6nhggLfn+gLVa#emIIp{4CTkdUQVbTaeQr=F%?qsJ4EfWzbKMVhov%4; z@EXpUnhMXioU!DlvNl+2Qde_( z^)5$-0X%K+H(y@ukJ7Q%WQ0PhYkGz`AbBHsK6`n{=UQAfFZ7Kwe`2ynvS!zj>0N(H z4{hnvw@Am$JH~IH^UgC@pH(TAG9?<9tc6F5D;2lNs*`ff;=@1_3Ud$9zTqro4(+>{ zO3)1SZO@=9EH)xII+T1J9m6m{zC}el(-s~w2&&qeu@XlA2Ia!R^m0rxi9O9{m?B%>4<*R- zEQrlci#PasuEPSRizh0uC-g-mu)IdiOck_!D^I7s*La@o9oTTS^_<_(CyY2G?43|8yX%x$O8x$?IcjV)f;8RXrhB;tb*i zRnv*P;xng7h;0MOaMM@eW0|zOB9te1x*fcBZMa+VdE9}pj}ilw9)9+o@`y=PU_5*mZ(J3C(_f==4*_vp zI`zNK9@DRzLx1O0GJxs-^yz-_D#K&MEi-{A0S7nm2ZS;%X$g_LHS&J3Pojn_Mho}~ zHG(EeFNxmbag2yNGrpgqe&Wwyu=p`Lt)q znQe0?ay)_M6zqgOF2Xczd8aQOUyZTR5n|dsfF7v)-E$aAf~QGzj#bauYx2;ro>n9D zFrL{5%p;)-sbaT`kd$Lv$h+MKt35DrO3G1AbX*>Ek=4u{$P2nHo89g4xaidbZhp7BW~((!?UORgKelpz*sEju%OaE>$We z(&`Z1P%%4qSq*hMi}Jzldsx6Fmvu;qZlDqLiK!b`;8d!@H6Po@ppmQ|y!P_kSfXqp zxDj|t-Uh)2+gOX52s%@%s_*4g!5o;lk_n{LQXeuZD54ZnL_+*ndJ*&Ast~>xT8w&~ z#U}Zol(l#$KE0GjKcHtDb_5A-N3EUZtn2)1^=N50xI-4wd`Kii}#pDUyVD6d?&uCGjM zXe_JnM0IC}+rILTf@Z_}KVB8A{SgLc}5{#{AtG z^F*|kgRi-0n~j}LD<4d5 zd~{cmFLq=oLwpcORN(Y=>fT7FrMu`>4&x=+Gaz^%RvmLZdt3P>UdrP$(5* zu6a>H9*0h0tpjtU5>hXuxlf&yA8uWV3ookym%76ThcX_JIEk&Zi-O?Z@N5waqAC&D z*m`+Q8UPd3zJ;0?eMZLBb#|tqQFfLgacm4q4Rp{#F^^DKh#T5qJ0= zS40&B40M`ix)27;$vfISLL3S$K#0J-k1k1{vpZ#oplMq?04|#L7Nv$~WeS&oKIC#^ z`LOq}Q#%`74hZYv6Pre&GEchzP~9sl6S1Ej%Vra)%`q#Qk?`-61ib_f1*AEICUjY` z3|5`V8b;)lQt5~)A^7IxhHM&|g{T#(oEY59a_}K)QuY3Jb0?1dG z?PHG--@_n~p8TZ)LWt<2Dquk~K|_wuP)~1dCvW}(d4&DMX`{&t{}kIVMA&_Hlw2^H z&%CCc{JD-usho>$U&BVq#9P?Aoo+`&;4y}Yi_}Fpq9aJN<|vs1YB=kkxeDn$j9hi>+u!SJt-~amwd^%a~|& zZkL$BSbrrR2I23b6j<63%LJUf!hOeEkjykUYZMvfu5;zG>jMc|j6t}QK zgU1{rZ*snlbX+>E!u+vRKXo`-Jl!rByvbQ*rE2s}q}-bemH?3=^2@7vMklD*7qFhS z*ue&C>>oeJlI>&dh+ls>)PT*JtGvRH{_t?1k#a-0Lz9Uhw%| z0l7=oE28HUrCnc*?7JmIJ{RV+x9EX49h2nU$u4&}A`E-1(E7!$5UHmcKujzt3Z~Ia zoSE>Zb3@poZ9Y@IXQI;V(6)9tH8)AWCh1Da2Jw1)7Y!rtHexfdiZDc zslMXMB6Y#Om|IOy(0Y!G#awgst?#eVgw4P%ev`80JFAK&4g?gGdI(A%E00D4wdFbLdx5WYS}yKsMVdwVrTfM4qTgvhO+*@okP0$PzReSfDfx z%iqqr^|#*=H!;iLEEkxq;B^=R`!O{bP<96LD}T-Yw2<(|gDo;hw#o$dZi#J;?CZ!#A9-yZQfZ-S9?GkFT1yQtW(ot9pPfD-82*NXcD(K z(LTEhK)Qdop*6dOKb{O7h&>FC%Z6p_=Xy|~Eb_{3$`5i8$yI5D&>L`(I~CVT-k#4x zaLB%`Jtzo*Q&7At3-mj)6rzYulmBK~zMhqRTeVG1iE2L&mf~C)rcQ|sB5xO?`!0ol zVp!%)b0c%q8cVWpP64rSM6ojFNAwDrLI+ZTZ`+X~V?&$Y?@kge)a0Du{z)(gNReFF zY)*z$mR(byegDfvo@h%2sla`NHVrfcCwVH3S_(Qpx;)GFD{(iEWs60~aYKZiybhK0 zJ>V#d4GLeGjJ)z*UiLL<^;t9o>?%+R(nj7|hDZl~1>z1PVCojY7jM@GR^b#=wF1N+ zvlPV%M4{~sbjRc}^v9*kQoeQWn)=2v$9eOu9@kAlcLMcB-op)P-dh z@>wNlV|VnGXMe08C+)oviNh@IiY%+ZH@hKBFR!=J*?}akaonrD#pom-FsU}h-R+dQ zeG_N$%z?On9vXs$-|4HbAG&c&tS!aY*U4y_m<0ZtM$Lk5d@m2adOQ~saI0vUP%2HheuB1(!?x3{`_KsP|p(`?5tLf3O*Dj<(Yb$ z8SQ01oe<^^4qAArdaFu{$4c7r@8B7=oCD_sjh9@3Jx!MEm&Jl?9cLvOH1M&h9#3sM z=rqE&bzdURY`+MZ!ffO`fM(=V;H+Gx|KYBMfHU>_~^ER{dG53rTF?qMCINxaUDC?T-TAfpcdKw=Q9uV{pRO9 z_Hh;1HyjNnjdtxYJ*~55QFXt8s^k_?d#1zNACo5L z)@W5Q2q}W{bt4Lrd1^EJgCJXI1Etf=ZSzu%c-1}vgRQPw1ZVPPqn%it)Di36k{^#t zt#h()e?^fcf029tYs@Tm;f12R_KMul6n8q}>|H%FNb!-F@Z|S`ly>;H;c6Clr)RK? zOp9zTtwol4Qkiy+3MLxx*-FxucBTEt7FO6nS_np6(P&kO?ZI#Sk(w$-x)pmM*#a8W z)UjDLw`L~r2@5exj_j*HyA`tocdz0ciAy%|&ioCvDw$Im4>xXJaBAWwpuMjmrewV| z6KS@18`s-$Qtvu>fo3Kn|rry(akLO1Nk|6Y=OA!{5k|w0eD%Io}T*)h&Z6U=}%nJcoDcHfqNCz zHD^iL0{ByNiuT9vWF1QKGa6G1fFeQeU*i0H`qAUFxtm0-9FjUvikT_e;+AXW4}=!W zQ%V!^)ZM5)R@u8|us@+5{#+GIcxL`71CL?!Q14B>1X}Xw)=MK!m!{kr5`SqYi$N|2 z+2hpZH)Ys+^+<-V#mD!T60by@iYhWU__Coe<%FFt5ho*C90O*>?{GDW&?o*PRQWY` z|Fe7uShvtJ@bg7%hY&%=nju%H$Nc?^v?D(2P2 zdG#$>qs+K@)LZtxFlPhy4{pxW{-VkR6k--EuGuyF;{4i2O5iVg6$OQNJPocy(IlNl z*DV@i>U(**qdJWzD|?%@hmEZ7wqo~Z z)$?b8rGs>9C03;kmDCrOG?j3>Cr}&6uEe7SDqLk3akdtoN~X$V*pnu>e7-cH9WW6h zqV&v_zB_;*L$QJa+%8WAY&LquPmMKr>NQtNu%XbQ8s=qtedCRbP{Wl`da<14Tbqes z^GT-u4@qdN+;JdbLDz=lNm*w?tV1I$1dx{$vzoX%^bZ?Fg(@<$v6vrZQYnE|8%0}gz^{oDAT?I6$(e8AuFgXt(~ z<&5pj^#6+w`p0p<&;kD(_XoZo{D6RT|3&u)y+8Q)$^V~x{MEQW>41Qb?SH=iJ`VU( zo`*`qAN0UK@4tPIKjj7ie}2c`<@@h;(9iZi_U7Yf6)Jr@sIR> z>gy+8AmD%M3G}F&-}LjJ`T+ip=MQ;)>hpI!{lp6b{jTT#!uz{C;2(1R-Vez1yIy|k z<5ABK8!3-fofMR`yblGHb`Q2ErY)zh1aLHdsJS$HNafnt=o?Vdit0N%TH5H@QcwbD zrEDzq>~$aNG%3XFANxL(j)ItJfDbLdp)j_z;Cm?F1W@p?(gEohfM6gqh@O#&p79Nk zo*W1yf9NM}srP^DB4?v*Wu>q8kVe)vvwf%nm6GFEq7kq+Gvm>=uy~{`XJl*(c=&(d zL5Syp3o3wuzK!hzalj9D9(p{8A!h8L4|rsQmfJ?x=;77E-iea(VHfCe(SDqCzpm6j z>RcstOl0jI>RKfL49t&NY#UoUz{6Dh`-C=#`JvG8FA~~&D$16#9atWdrOc6MpMfm& zNtn-kcCv-T>LRpr%~jfws~Dt%-o!u%Lw7eHu(a`qVyXtKr0eG~fPbMR zrS`<|LQ^QMM1;W#!AJOJ2@osqB?^ZP;pffw1{MyIl1c*pU0g3W5jQDX=gU||G!j^9 zoEnJPuRd~V@A=5Wse58zs>lf8Y6QHa)56;(ydBgKF^<{P6d@2tVPau?VZ7<4L;^+1 z?6WY$qM4VpNO}ZJf{Wl7^MbW^*50mG@vPcI#DOZF%=%G1>4i37&_eeXU?~$JM29Vu zu0z$LW;I5$Li_;2mr!B^!X)vzkk}_?nj}rWY_}j|bwps28KLEC zI0$IEN{Fa*gAgZ(%USUF;A}_ANt46x%qS{|zk+^GiF?@_FE~YQF-jFk80s?@1ftnx zjKW^8Guen&@LHY;b>=LnBtkZ6;2w%`Q`ZszF01UCX)`P|?1P4Jl~-15#6$WD@_^DETc)1sV!rTxuKDojWTM5M(^n@r#>H|;f{HCt7ua&92(h1fxBrsT z=)R$=w9m~E&sA}M-+UwR4!la+HZD-#cs{EhG3CBm-izv)`ReIW?~1v1&T2FU#V*=> z&o(swA$5}wc}fkNAf`RE3^+Ev>Gj5Xm*Od#Ov2@KWaVkzMc4{OKu^BV&>(ZP;Kb|W zeIjaUm|F*4#Ns&p?*|_DkX506wpuKaXx)UVlDP;m6T#0Bz6$gTS=~Nc!Mv$OQqQvA z>wTqy`eH3!(O%^msq+ zO=#iWT^vMi#9DTjdD%Y5cGYdAFAY$j+`JG`B(QZQ`Oz zKH))i*{O8mde&wyB42D;;Sqp44dCotGb6VUSFclp4w#hO;dwEbqK4U(h%lP)m$_{= zToDORDK4MasgZf0#LuE};n5KItgJwi_K^`7tgpcYe6DDx*OrBuF06Ff{`dsxY=K;0 zHPv}A!EF#NoZ5Ae#I!>NTs)k<9#&gyw8_T$nH4;HNPWt%BkH2cnG@sid33b65Ys)W z`pmT2Ir$@F<5Xg*PCtG*QR!rJYjc*MqnnBNfXl0iwbQ#Q51V?T_!GU#xd8%mg>MO{ zrbp=4zF%$)jfkPJ(htOT#K(2aJ#4$I@#T@9a*HoQ)BDjd#jY{xbM9Z2EQOYAH`2gi zBp{VV!eNfajg2vdZG=O1e*_f^<9rLt88vD9M9LbT%AgS7&di{I%W~Jl(BalBJdK(cVX}IKU(GBelCwliZ7z(HmaW3ed5Eyt;??=QeBW)pJ4*-a-11Rt;=_cRF+M z$1Bwtj0w)jAvPc7R_H53ey=# zxw$7DsnjtcvLTzX@VFE(My7#+r&yxw@1Z>QAjFjrI=?bUn6ig$Q5Eo+g&&S)u4>*p zeSWpdP>K{0vUOqlEiPav{L6-L-86CZ^^$q5Pc5dVf35VJL-29_l6&eVZkjpxt*R$e z)xq=YZG#V4zSXFb$UEa#weal&uO_W|H4K*-^QaeRO^l0;Jm^bvl_T6PW@Ho?=WpT3 zQnDG05Q-#pI)&}w=Xp#+bQ|I)Cgjphz~;|ArLQEDKgmlB+g5}pZOX}PVWy!>b$|FA zqhsgwUPbv}RG&RV$=RYn;A={0=Dh1XX@=N7O8<^(ap_c+oo?`19{7{pStnLJcD zT(MFIEei?T2ISQ^Jw3$Rw?2LtME-d2T#w+A>nWh7fcAf*CFZ}VMU~Mv0MH6s=;{AB zPQuIpcsMU2YwV&AczC2${Ov3W-NSj3$5SMhmUaNqOVqQjCsELjBr*Vq61Av+X5`d@vF-CQ zndSn@={8P-3BIgPmoeY*=Fe31`l~y;8W{4j2nAj!mMnIBBGiA68?g|Zb6WZ>n4xga zEj&epe|?S6rFV<9V(*lxVs%1LPf_LAG8hx%{QFR6+$?Q5eG3Y4Ec2I_=(}1W=8hgZ zOl>qaVb)%@edR4UNY;M3j$G>t)k*!UdzA20$&1~WjcRk9ZvM|{tb*UfOCI-E-aXX{ g0G#}<25s%MZS0&L97T8#9Sa>3JSi!^qyYT?0j$k}&j0`b From 7af50a566fe2317c8466a84249b5483152eb4b42 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Fri, 14 Jun 2024 10:51:46 +0300 Subject: [PATCH 12/29] Update CI script --- .github/workflows/main.yml | 79 ++++++++++++-------------------------- 1 file changed, 24 insertions(+), 55 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2b72339..f8c9109 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,69 +1,38 @@ -# This is a basic workflow to help you get started with Actions +name: Build latest PDF -name: CI - -# Controls when the workflow will run on: - # Triggers the workflow on push or pull request events but only for the main branch push: + branches: + # PRs can only use caches from their target branch. We therefore need to + # make sure we run on 'main' too. + - main pull_request: - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: -# A workflow run is made up of one or more jobs that can run sequentially or in parallel +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on + style: + name: Build latest PDF runs-on: ubuntu-latest - - # Steps represent a sequence of tasks that will be executed as part of the job steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - name: Set up Git repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - # First run of pdflatex. - - name: First pdflatex FormalLanguageConstrainedReachabilityLectureNotes - uses: dante-ev/latex-action@latest - with: - working_directory: tex - root_file: FormalLanguageConstrainedReachabilityLectureNotes.tex - compiler: pdflatex - args: -interaction=nonstopmode -shell-escape - - # Bibliography generation - - name: bibtex FormalLanguageConstrainedReachabilityLectureNotes - uses: dante-ev/latex-action@latest + - name: Compile LaTeX document + uses: xu-cheng/latex-action@v3 with: - working_directory: tex - root_file: FormalLanguageConstrainedReachabilityLectureNotes.aux - compiler: bibtex - args: - - # Second compilation - - name: Second pdflatex FormalLanguageConstrainedReachabilityLectureNotes - uses: dante-ev/latex-action@latest - with: - working_directory: tex - root_file: FormalLanguageConstrainedReachabilityLectureNotes.tex - compiler: pdflatex - args: -interaction=nonstopmode -shell-escape - - # Final compilation - - name: Final pdflatex FormalLanguageConstrainedReachabilityLectureNotes - uses: dante-ev/latex-action@latest + root_file: tex/main.tex + work_in_root_file_dir: true + latexmk_use_lualatex: true + + - name: Rename PDF + run: | + mv tex/main.pdf tex/FormalLanguageConstrainedReachabilityLectureNotes.pdf + + - name: Upload PDF file + uses: actions/upload-artifact@v4 with: - working_directory: tex - root_file: FormalLanguageConstrainedReachabilityLectureNotes.tex - compiler: pdflatex - args: -interaction=nonstopmode -shell-escape - - # Publish compiled pdf - - name: Upload - uses: actions/upload-artifact@v2 - with: name: FormalLanguageConstrainedReachabilityLectureNotes_latest path: tex/FormalLanguageConstrainedReachabilityLectureNotes.pdf - From ba1af0c6c2ebf70f9b9e4179b67a809b40776875 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Fri, 14 Jun 2024 10:59:13 +0300 Subject: [PATCH 13/29] Install fonts in CI --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f8c9109..5613311 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,6 +26,7 @@ jobs: root_file: tex/main.tex work_in_root_file_dir: true latexmk_use_lualatex: true + extra_system_packages: "font-liberation" - name: Rename PDF run: | From feeb696889126bf3f2fa729c10d2a122e13caccd Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Fri, 14 Jun 2024 11:04:17 +0300 Subject: [PATCH 14/29] Enable shell escape --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5613311..0d4ae26 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,6 +27,7 @@ jobs: work_in_root_file_dir: true latexmk_use_lualatex: true extra_system_packages: "font-liberation" + latexmk_shell_escape: true - name: Rename PDF run: | From f2d767ff825c46e71904e88e3787fba544e1efd0 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Fri, 14 Jun 2024 12:40:53 +0300 Subject: [PATCH 15/29] Keep tex/figures/exteralized directory --- .gitignore | 1 + tex/figures/externalized/.gitkeep | 0 2 files changed, 1 insertion(+) create mode 100644 tex/figures/externalized/.gitkeep diff --git a/.gitignore b/.gitignore index 5cd9a02..bd3b898 100644 --- a/.gitignore +++ b/.gitignore @@ -277,4 +277,5 @@ TSWLatexianTemp* tex/FormalLanguageConstrainedReachabilityLectureNotes.pdf tex/figures/externalized/* +!tex/figures/externalized/.gitkeep tex/main.pdf diff --git a/tex/figures/externalized/.gitkeep b/tex/figures/externalized/.gitkeep new file mode 100644 index 0000000..e69de29 From f3389a78099d3fe4f6b911a93e894d85ff80a28f Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sun, 16 Jun 2024 11:38:28 +0300 Subject: [PATCH 16/29] Fixes in Linear Algebra --- tex/LinearAlgebra.tex | 107 ++++++++++++++++++++-------------------- tex/main.tex | 3 +- tex/styles/language.tex | 1 - tex/styles/utils.tex | 1 - 4 files changed, 55 insertions(+), 57 deletions(-) diff --git a/tex/LinearAlgebra.tex b/tex/LinearAlgebra.tex index b9527fd..f294e17 100644 --- a/tex/LinearAlgebra.tex +++ b/tex/LinearAlgebra.tex @@ -106,7 +106,6 @@ \section{Бинарные операции и их свойства} \item Операция конкатенации на строках $\cdot$ является ассоциативной: \[("a" \cdot "b") \cdot "c" = "a" \cdot ("b" \cdot "c") = "abc".\] \item Операция возведения в степень (над целыми числами) $\hat{\mkern6mu}$ не является ассоциативной: - \marginnote{TODO: Мне не нравится этот символ. Может убрать обозначения из текста выше, а в формуле нарисовать башенку?} \[(2\hat{\mkern6mu}2)\hat{\mkern6mu}3 = 4 \hat{\mkern6mu} 3 = 64 \neq 256 = 2 \hat{\mkern6mu} 8 = 2\hat{\mkern6mu}(2\hat{\mkern6mu}3).\] \end{itemize} \end{example} @@ -412,35 +411,32 @@ \section{Матрицы и вектора} \item \emph{алгебраические}~--- определение таковых опирается на свойства алгебраической структуры, над которой построена матрица. \end{itemize} -\marginnote{TODO: Пример ниже чуток вылезает} Примерами структурных операций является \emph{транспонирование}, \emph{взятие подматрицы} и \emph{взятие элемента по индексу}. -\begin{marginfigure} - \[ - \begin{pmatrix} - "a" & "ba" & "cb" \\ - "ac" & "bab" & "b" - \end{pmatrix}^\top = - \begin{pmatrix} - "a" & "ac" \\ - "ba" & "bab" \\ - "cd" & "b" - \end{pmatrix} - \] - \caption{Пример транспонирования} -\end{marginfigure} +\marginnote{ + \begin{example} + Транспонирование матрицы. + \[ + \begin{pmatrix} + "a" & "ba" & "cb" \\ + "ac" & "bab" & "b" + \end{pmatrix}^\top = + \begin{pmatrix} + "a" & "ac" \\ + "ba" & "bab" \\ + "cd" & "b" + \end{pmatrix} + \] + \end{example} +} \begin{definition}[Транспонирование матрицы] Пусть дана матрица $M_{n \times m}$. - Тогда результат её \emph{транспонирования}, это такая матрица $M'_{m \times n}$, что $M'[i,j] = M[j,i]$ для всех $0\leq i \leq m - 1$ и $0\leq j \leq n - 1$. + Тогда результат её \emph{транспонирования}, это такая матрица $M'_{m \times n}$, что $M'[i,j] = M[j,i]$ для всех $i \in [0 : m - 1]$ и $j \in [0 : n - 1]$. Операцию транспонирования принято обозначать как $M^\top$. \end{definition} \begin{definition}[Прямая сумма матриц] - \marginnote{TODO: Здесь точно большой плюс? - TODO: Я ниже заменил $..$ на $\dots$ может быть это не самая лучшая идея, хотя вроде дальше особо такое не используется. - У Виноградова в учебнике используется довольно прикольная как по мне нотация $[a : b] = \{x \mid a \leq x \leq b\}$, как раз для целочисленных интервалов. - TODO: "Рис" надо заменить на "Пример"} Пусть даны матрицы $M_{n_1 \times m_1}$ и $N_{n_2 \times m_2}$. Тогда \emph{прямой суммой} этих матриц называется матрица $L_{(n_1 + n_2) \times (m_1 + m_2)}$ вида \[ @@ -450,38 +446,42 @@ \section{Матрицы и вектора} 0 & N \end{pmatrix} \] - Где 0 обозначает нулевой блок. Прямая сумма обозначается $L = M \bigoplus N$. + Где 0 обозначает нулевой блок. Прямая сумма обозначается $L = M \oplus N$. \end{definition} -\begin{marginfigure} - \begin{align*} - \begin{pmatrix} - "a" & "ba" & "cb" \\ - "ac" & "bab" & "b" - \end{pmatrix} & [0 \dots 1, 1 \dots 2] = \\ - ={} & \begin{pmatrix} - "ba" & "cb" \\ - "bab" & "b" - \end{pmatrix} - \end{align*} - \caption{Пример взятия подматрицы} -\end{marginfigure} +\marginnote{ + \begin{example} + Взятие подматрицы. + \begin{multline*} + \begin{pmatrix} + "a" & "ba" & "cb" \\ + "ac" & "bab" & "b" + \end{pmatrix} [0 : 1, 1 : 2] = \\ + = \begin{pmatrix} + "ba" & "cb" \\ + "bab" & "b" + \end{pmatrix} + \end{multline*} + \end{example} +} \begin{definition}[Взятие подматрицы] Пусть дана матрица $M_{n\times m}$. - Тогда $M_{n \times m}[i_0 \dots i_1, j_0 \dots j_1]$~--- это такая $M'_{(i_1 - i_0 + 1) \times (j_1 - j_0 + 1)}$, что $M'[i, j] = M[i_0 + i, j_0 + j]$ для всех $0 \leq i \leq i_1 - i_0 + 1$ и $0 \leq j \leq j_1 - j_0 + 1$. + Тогда $M_{n \times m}[i_0 : i_1, j_0 : j_1]$~--- это такая $M'_{(i_1 - i_0 + 1) \times (j_1 - j_0 + 1)}$, что $M'[i, j] = M[i_0 + i, j_0 + j]$ для всех $i \in [0 : i_1 - i_0 + 1]$ и $j \in [0 : j_1 - j_0 + 1]$. \end{definition} -\begin{marginfigure} - \[ - \begin{pmatrix} - "a" & "ba" & "cb" \\ - "ac" & "bab" & "b" - \end{pmatrix}[0, 1] = "ba" - \] - \caption{Пример взятия элемента по индексу} -\end{marginfigure} +\marginnote{ + \begin{example} + Взятие элемента по индексу. + \[ + \begin{pmatrix} + "a" & "ba" & "cb" \\ + "ac" & "bab" & "b" + \end{pmatrix}[0, 1] = "ba" + \] + \end{example} +} \begin{definition}[Взятие элемента по индексу] - \emph{Взятие элемента по индексу}~--- это частный случай взятия подматрицы, когда начало и конец\enquote{среза} совпадают: $M[i, j] = M[i \dots i, j\dots j]$ + \emph{Взятие элемента по индексу}~--- это частный случай взятия подматрицы, когда начало и конец\enquote{среза} совпадают: $M[i, j] = M[i : i, j : j]$ \end{definition} Из алгебраических операций над матрицами нас в дальнейшем будут интересовать \emph{поэлементные операции}, \emph{скалярные операции}, \emph{матричное умножение}, \emph{произведение Кронекера}. @@ -550,7 +550,7 @@ \section{Матрицы и вектора} \begin{definition}[Матричное умножение] \label{def:MxM} Пусть $G = (S, \oplus, \otimes)$~--- полукольцо, $M_{n \times m}$, $N_{m\times k}$~--- две матрицы над этим полукольцом. - Тогда $M \cdot N = P_{n \times k}$, такая, что $P[i, j] = \bigoplus_{0 \leq l < m} M[i, l] \otimes N[l, j]$. + Тогда $M \cdot N = P_{n \times k}$, такая, что $P[i, j] = \bigoplus_{l \in [0 : m - 1]} M[i, l] \otimes N[l, j]$. \end{definition} \begin{example} @@ -582,19 +582,17 @@ \section{Матрицы и вектора} \] \end{example} - \begin{definition}[Произведение Кронекера] Пусть $G = (S, \circ)$~--- полугруппа, $M_{m \times n}$ и $N_{p \times q}$~--- две матрицы над этой полугруппой. - Тогда произведение Кронекера или тензорное произведение матриц $M$ и $N$~--- это блочная матрица $C$ размера $mp \times nq$, вычисляемая следующим образом: - \[ - C = A \otimes B = + Тогда \emph{произведение Кронекера} или \emph{тензорное произведение} матриц $M$ и $N$~--- это блочная матрица $K$ размера $mp \times nq$, вычисляемая следующим образом: + \begin{multline*} + K = M \otimes N = \\ \begin{pmatrix} \mathrm{scalar}(M[0,0],N,\circ) & \cdots & \mathrm{scalar}(M[0,n-1],N,\circ) \\ \vdots & \ddots & \vdots \\ \mathrm{scalar}(M[m-1,0],N,\circ) & \cdots & \mathrm{scalar}(M[m-1,n-1],N,\circ) \end{pmatrix} - \] - \marginnote{TODO: Здесь вылезло} + \end{multline*} \end{definition} \begin{remark} @@ -603,6 +601,7 @@ \section{Матрицы и вектора} При этом всегда существуют две матрицы перестановок $P$ и $Q$ такие, что $A \otimes B = P(B \otimes A)Q$. \end{remark} +\begingroup \newcommand{\examplemtrx} { \begin{pmatrix} @@ -650,6 +649,7 @@ \section{Матрицы и вектора} \end{pNiceArray} \end{align*} \end{example} +\endgroup \section{Теоретическая сложность умножения матриц} @@ -697,7 +697,6 @@ \section{Теоретическая сложность умножения мат Пусть $A$ и $B$~--- две квадратные матрицы размера $2^n \times 2^n$ над кольцом $R=(S, \oplus, \otimes)$. Если размер умножаемых матриц не является натуральной степенью двойки, то дополняем исходные матрицы дополнительными нулевыми строками и столбцами. Наша задача найти матрицу $C = A \cdot B$. -\marginnote{TODO: Только здесь заметил, а не хотим ли мы красную строку, всё-таки в России живем?} Разделим матрицы $A, B$ и $C$ на четыре равные по размеру блока. \[ diff --git a/tex/main.tex b/tex/main.tex index 8c04316..2533084 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -1,7 +1,8 @@ \documentclass[ fontsize=10pt, a4paper, - twoside=false + twoside=false, + parskip=false ]{kaobook} \input{styles/language.tex} diff --git a/tex/styles/language.tex b/tex/styles/language.tex index 6d6f733..2017ed0 100644 --- a/tex/styles/language.tex +++ b/tex/styles/language.tex @@ -3,4 +3,3 @@ \setotherlanguage{english} \usepackage[autostyle]{csquotes} % Правильные кавычки в зависимости от языка -\usepackage{microtype} % Полезные типографические ништячки diff --git a/tex/styles/utils.tex b/tex/styles/utils.tex index 50610ad..bedf01a 100644 --- a/tex/styles/utils.tex +++ b/tex/styles/utils.tex @@ -1,5 +1,4 @@ \usepackage{xurl} % Разрешить переносить URL на любой букве -\usepackage{booktabs} \usepackage[noheader]{gitver} \NewDocumentCommand{\email}{m}{\href{mailto:#1}{#1}} % Кликабельный email From 3059826d683ce679d90c61cf4d14ccbc9e8c55cb Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sun, 16 Jun 2024 12:20:54 +0300 Subject: [PATCH 17/29] Redo algorithm in Linear Algebra --- tex/LinearAlgebra.tex | 48 ++++++++++++++++--------------------------- tex/kao.sty | 2 +- tex/main.tex | 5 ++++- tex/styles/utils.tex | 8 ++++++++ 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/tex/LinearAlgebra.tex b/tex/LinearAlgebra.tex index f294e17..d16e7b1 100644 --- a/tex/LinearAlgebra.tex +++ b/tex/LinearAlgebra.tex @@ -431,7 +431,7 @@ \section{Матрицы и вектора} } \begin{definition}[Транспонирование матрицы] Пусть дана матрица $M_{n \times m}$. - Тогда результат её \emph{транспонирования}, это такая матрица $M'_{m \times n}$, что $M'[i,j] = M[j,i]$ для всех $i \in [0 : m - 1]$ и $j \in [0 : n - 1]$. + Тогда результат её \emph{транспонирования}, это такая матрица $M'_{m \times n}$, что $M'[i,j] = M[j,i]$ для всех $i \in [0 \rng m - 1]$ и $j \in [0 \rng n - 1]$. Операцию транспонирования принято обозначать как $M^\top$. \end{definition} @@ -456,7 +456,7 @@ \section{Матрицы и вектора} \begin{pmatrix} "a" & "ba" & "cb" \\ "ac" & "bab" & "b" - \end{pmatrix} [0 : 1, 1 : 2] = \\ + \end{pmatrix} [0 \rng 1, 1 \rng 2] = \\ = \begin{pmatrix} "ba" & "cb" \\ "bab" & "b" @@ -466,7 +466,7 @@ \section{Матрицы и вектора} } \begin{definition}[Взятие подматрицы] Пусть дана матрица $M_{n\times m}$. - Тогда $M_{n \times m}[i_0 : i_1, j_0 : j_1]$~--- это такая $M'_{(i_1 - i_0 + 1) \times (j_1 - j_0 + 1)}$, что $M'[i, j] = M[i_0 + i, j_0 + j]$ для всех $i \in [0 : i_1 - i_0 + 1]$ и $j \in [0 : j_1 - j_0 + 1]$. + Тогда $M_{n \times m}[i_0 \rng i_1, j_0 \rng j_1]$~--- это такая $M'_{(i_1 - i_0 + 1) \times (j_1 - j_0 + 1)}$, что $M'[i, j] = M[i_0 + i, j_0 + j]$ для всех $i \in [0 \rng i_1 - i_0 + 1]$ и $j \in [0 \rng j_1 - j_0 + 1]$. \end{definition} \marginnote{ @@ -481,14 +481,14 @@ \section{Матрицы и вектора} \end{example} } \begin{definition}[Взятие элемента по индексу] - \emph{Взятие элемента по индексу}~--- это частный случай взятия подматрицы, когда начало и конец\enquote{среза} совпадают: $M[i, j] = M[i : i, j : j]$ + \emph{Взятие элемента по индексу}~--- это частный случай взятия подматрицы, когда начало и конец \enquote{среза} совпадают: $M[i, j] = M[i \rng i, j \rng j]$. \end{definition} Из алгебраических операций над матрицами нас в дальнейшем будут интересовать \emph{поэлементные операции}, \emph{скалярные операции}, \emph{матричное умножение}, \emph{произведение Кронекера}. \begin{definition}[Поэлементные операции] Пусть $G = (S, \circ)$~--- полугруппа% - \sidenote[][*2]{Здесь, как и в дальнейшем, требование к структуре быть полугруппой не обязательно. + \sidenote{Здесь, как и в дальнейшем, требование к структуре быть полугруппой не обязательно. Оно лишь позволяет нам получить ассоциативность соответствующих операций над матрицами, что может оказаться полезным при дальнейшей работе.}% , $M_{n \times m}$, $N_{n \times m}$~--- две матрицы одинакового размера над этой полугруппой. Тогда $\mathrm{ewise}(M, N, \circ) = P_{n \times m}$, такая, что $P[i, j] = M[i, j] \circ N[i, j]$. @@ -550,7 +550,7 @@ \section{Матрицы и вектора} \begin{definition}[Матричное умножение] \label{def:MxM} Пусть $G = (S, \oplus, \otimes)$~--- полукольцо, $M_{n \times m}$, $N_{m\times k}$~--- две матрицы над этим полукольцом. - Тогда $M \cdot N = P_{n \times k}$, такая, что $P[i, j] = \bigoplus_{l \in [0 : m - 1]} M[i, l] \otimes N[l, j]$. + Тогда $M \cdot N = P_{n \times k}$, такая, что $P[i, j] = \bigoplus_{l \in [0 \rng m - 1]} M[i, l] \otimes N[l, j]$. \end{definition} \begin{example} @@ -659,32 +659,20 @@ \section{Теоретическая сложность умножения мат Для начала построим наивный алгоритм, сконструированный на основе определения произведения матриц. Такой алгоритм представлен на листинге~\ref{algo:MxM}. -\marginnote{TODO: Ничего против не имею, но точно ли название "Листинг" здесь хорошо? - TODO: Оформление алгоритмов точно надо обсудить, потому что я в этом мало понимаю.} +\marginnote{TODO: Оформление алгоритмов точно надо обсудить, потому что я в этом мало понимаю.} Его работу можно описать следующим образом: для каждой строки в первой матрице и для каждого столбца в второй матрице найти сумму произведений соответствующих элементов. Данная сумма будет значением соответствующей ячейки результирующей матрицы. -\begin{algorithm} - \caption{Наивное перемножение матриц} - \label{algo:MxM} - - \DontPrintSemicolon - \SetAlgoNoLine - \SetAlgoNoEnd - - \SetKwProg{KwFn}{function}{}{} - \SetKwFunction{FMatrixMult}{MatrixMult} - - \KwFn{\FMatrixMult{$M_1$, $M_2$, $G = (S, \oplus, \otimes)$}}{ - $M_3 =$ empty matrix of size $n \times n$\; - \For{$i \in 0 \dots n-1$}{ - \For{$j \in 0 \dots n-1$}{ - \For{$k \in 0 \dots n-1$}{ - $M_3[i, j] = M_3[i, j] \oplus ( M_1[i, k] \otimes M_2[k, j])$ - } - } - } - \KwRet{$M_3$} - } + +\begin{algorithm}{Наивное умножение матриц}{MxM} + \begin{pseudo}[] + \kw{function} \pr{MatrixMult}(M_1, M_2, G = (S, \oplus, \otimes)) \\+ + $M_3 = $ пустая матрица размера $n \times n$ \\ + \kw{for} $i \in [0 \rng n - 1]$ \\+ + \kw{for} $j \in [0 \rng n - 1]$ \\+ + \kw{for} $k \in [0 \rng n - 1]$ \\+ + $M_3[i, j] = M_3[i, j] \oplus (M_1[i, k] \otimes M_2[k, j])$ \\--- + \kw{return} $M_3$ + \end{pseudo} \end{algorithm} Сложность наивного произведения двух матриц составляет $O(n^3)$ из-за тройного вложенного цикла, где каждый уровень вложенности привносит $n$ итераций. diff --git a/tex/kao.sty b/tex/kao.sty index 54174be..5e5b33c 100644 --- a/tex/kao.sty +++ b/tex/kao.sty @@ -1381,7 +1381,7 @@ %verbatim \preto{\@verbatim}{\topsep=0pt \partopsep=0pt } % Algorithms -\RequirePackage[linesnumbered, ruled, vlined]{algorithm2e} % Algorithms +% \RequirePackage[linesnumbered, ruled, vlined]{algorithm2e} % Algorithms % Special gliphs \RequirePackage{ccicons} % Creative Commons icons diff --git a/tex/main.tex b/tex/main.tex index 2533084..a93cdd2 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -14,7 +14,10 @@ \usepackage{kaobiblio} % Обертка для biblatex, позволяет печатать сноску сбоку \addbibresource{FormalLanguageConstrainedReachabilityLectureNotes.bib} -\SetAlgorithmName{Листинг}{листинг}{Список листингов} +\usepackage[]{pseudo} +\newtcbtheorem{algorithm}{Листинг}{pseudo/booktabs, float, floatplacement=h, separator sign={.}}{algo} + + \tikzexternalize diff --git a/tex/styles/utils.tex b/tex/styles/utils.tex index bedf01a..2d88773 100644 --- a/tex/styles/utils.tex +++ b/tex/styles/utils.tex @@ -2,3 +2,11 @@ \usepackage[noheader]{gitver} \NewDocumentCommand{\email}{m}{\href{mailto:#1}{#1}} % Кликабельный email + +%% : с чуть более узки расстоянием по бокам. +%% Определено в pseudo, потому пока что закомментировано +% \NewDocumentCommand \rng { } { +% \nolinebreak +% \mathinner { : } +% \nolinebreak +% } From f0ebe4e4be4782e6d4268830e3e7c81bad2f1933 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sun, 16 Jun 2024 21:24:07 +0300 Subject: [PATCH 18/29] Add Graph Theory Intro chapter --- tex/GraphTheoryIntro.tex | 663 +++++++++++++++++++++++++++ tex/Introduction.tex | 2 +- tex/LinearAlgebra.tex | 52 +-- tex/figures/graph/graph0.tex | 19 + tex/figures/graph/graph1.tex | 18 + tex/figures/graph/graph2.tex | 19 + tex/figures/graph/graph3.tex | 20 + tex/figures/graph/graph4.tex | 19 + tex/figures/graph/graph5.tex | 31 ++ tex/figures/graph/graph_BFS_1.tex | 19 + tex/figures/graph/graph_BFS_2.tex | 19 + tex/figures/graph/graph_BFS_3.tex | 19 + tex/figures/graph/graph_MS-BFS_1.tex | 19 + tex/figures/graph/graph_MS-BFS_2.tex | 19 + tex/figures/graph/path0.tex | 6 + tex/main.tex | 3 +- tex/styles/math.tex | 4 - tex/styles/tikz.tex | 5 +- 18 files changed, 922 insertions(+), 34 deletions(-) create mode 100644 tex/GraphTheoryIntro.tex create mode 100644 tex/figures/graph/graph0.tex create mode 100644 tex/figures/graph/graph1.tex create mode 100644 tex/figures/graph/graph2.tex create mode 100644 tex/figures/graph/graph3.tex create mode 100644 tex/figures/graph/graph4.tex create mode 100644 tex/figures/graph/graph5.tex create mode 100644 tex/figures/graph/graph_BFS_1.tex create mode 100644 tex/figures/graph/graph_BFS_2.tex create mode 100644 tex/figures/graph/graph_BFS_3.tex create mode 100644 tex/figures/graph/graph_MS-BFS_1.tex create mode 100644 tex/figures/graph/graph_MS-BFS_2.tex create mode 100644 tex/figures/graph/path0.tex diff --git a/tex/GraphTheoryIntro.tex b/tex/GraphTheoryIntro.tex new file mode 100644 index 0000000..3f6b624 --- /dev/null +++ b/tex/GraphTheoryIntro.tex @@ -0,0 +1,663 @@ +\setchapterpreamble[u]{\margintoc} +\chapter{Некоторые сведения из теории графов} +\label{chpt:GraphTheoryIntro} + +В данном разделе мы дадим определения базовым понятиям из теории графов, рассмотрим несколько классических задач из области анализа графов и алгоритмы их решения. +Кроме этого, поговорим о связи между линейной алгеброй и некоторыми задачами анализа графов. +Всё это понадобится нам при последующей работе. + +\section{Основные определения} + +\begin{definition}[Помеченный ориентированный граф] + \emph{Помеченный ориентированный граф} $\mbfscrG = \langle V, E, L \rangle$, где $V$~--- конечное множество вершин, $E$~--- конечное множество рёбер, т.ч. $E \subseteq V \times L \times V$, $L$~--- конечное множество меток на рёбрах. + В некоторых случаях метки называют \emph{весами}% + \sidenote{Весами метки называют, как правило, тогда, когда они берутся из какого-либо числового множества, например $\BbbR$ или $\BbbN$.} + и тогда говорят о \emph{взвешенном} графе. +\end{definition} + +\begin{definition}[Помеченный неориентированный граф] + В случае, если для любого ребра $(u, l, v)$ в графе также содержится ребро $(v, l, u)$, говорят, что граф \emph{неориентированный}. +\end{definition} + +\marginnote{ + \begin{example} + Пусть дан граф + \begin{align*} + \mbfscrG_1 = \langle V & =\{0, 1, 2, 3\}, \\ + E & =\{(0, a, 1), (1, a, 2), (2, a, 0), \\ + & \ \ \ (2, b, 3), (3, b, 2)\}, \\ + L & =\{a, b\} \rangle. + \end{align*} + Графическое представление графа $\mbfscrG_1$: + \begin{center} + \input{figures/graph/graph0} + \end{center} + $(0, a, 1)$ и $(3,b,2)$~--- это рёбра графа $\mbfscrG_1$. + При этом $(3, b, 2)$ и $(2, b, 3)$~--- это разные рёбра. + \end{example} +} +В дальнейшем речь будет идти о конечных ориентированных помеченных графах. +Мы будем использовать термин \emph{граф} подразумевая именно конечный ориентированный помеченный граф, если только не оговорено противное. + +Также мы будем считать, что все вершины занумерованы подряд с нуля. +То есть можно считать, что $V$~--- это отрезок $[0 \rng |V| - 1]$, где $|V|$~--- мощность множества $V$. + +\begin{definition}[Путь] + \emph{Путём} $\pi$ в графе $\mbfscrG$ будем называть последовательность рёбер такую, что для любых двух последовательных рёбер $e_1 = (u_1, l_1, v_1)$ и $e_2 = (u_2, l_2, v_2)$ в этой последовательности, конечная вершина первого ребра является начальной вершиной второго, то есть $v_1 = u_2$. + Будем обозначать путь из вершины $v_0$ в вершину $v_n$ как $v_0 \pi v_n$. + Иными совами, + \[v_0 \pi v_n = e_0,e_1, \dots, e_{n-1} = (v_0, l_0, v_1),(v_1,l_1,v_2),\dots,(v_{n-1},l_{n-1},v_n).\] +\end{definition} +Часто для представления пути мы буем использовать следующие нотации: +\begin{center} + \input{figures/graph/path0.tex} +\end{center} +или +\[ + v_0 \xrightarrow[]{l_0} v_1 \xrightarrow[]{l_1} v_2 \xrightarrow[]{l_2} \ldots \xrightarrow[]{l_{n-2}} v_{n-1} \xrightarrow[]{l_{n-1}} v_n. +\] + +\begin{example} + $(0,a,1), (1,a,2) = 0 \pi_1 2$~--- путь из вершины 0 в вершину 2 в графе $\mbfscrG_1$. + При этом $(0, a, 1), (1, a, 2), (2, b, 3), (3, b, 2) = 0 \pi_2 2$~--- это тоже путь из вершины 0 в вершину 2 в графе $\mbfscrG_1$, но он не равен $0 \pi_1 2$. +\end{example} + +Кроме того, нам потребуется отношение, отражающее факт существования пути между двумя вершинами. + +\begin{definition}[Достижимость в графе] + \label{def:reach} + \emph{Отношение достижимости} в графе: $(v_i,v_j) \in P \iff \exists v_i \pi v_j$. + \marginnote{TODO: Не надо ли множество $P$ ввести аккуратнее?} +\end{definition} + +Отметим, что в некоторых задачах удобно считать по умолчанию, что $(v_i,v_i) \in P$, однако наше определение такого не допускает. +Исправить ситуацию можно явно добавив петли $(v_i,l,v_i)$ для всех вершин. + +Один из способов задать граф~--- это задать его \emph{матрицу смежности}. + +\begin{definition}[Матрица смежности] + \emph{Матрица смежности} графа $\mbfscrG = \langle V, E, L \rangle$~--- это квадратная матрица $M$ размера $n \times n$, где $|V| = n$, построенная над коммутативным моноидом $\BbbG = (S, \circ: S \times S \to S)$, который конструируется следующим образом. + \begin{enumerate} + \item $L \subseteq S$. + \item $\circ$~--- коммутативная бинарная операция. + \item Существует $\Bbbzero \in (S \setminus L)$~--- нейтральный элемент относительно $\circ$. + \end{enumerate} + При этом $M[i,j] = \bigcirc_{(i, l, j) \in E}l$, где $\bigcirc_\varnothing = \Bbbzero$. +\end{definition} + +Заметим, что наше определение матрицы смежности отличается от классического, в котором матрица является булевой и отражает лишь факт наличия хотя бы одного ребра. +То есть $M[i,j] = 1 \iff \exists e = (i,\_,j) \in E$. + +\begin{marginfigure} + \caption{Неориентированный граф} + \label{gr:graph1} + \begin{center} + \input{figures/graph/graph1.tex} + \end{center} +\end{marginfigure} +\begin{example}[Пример матрицы смежности неориентированного графа] + \label{exmpl:undirectedGraphMatrix} + Пусть дан неориентированный граф (см. рисунок \ref{gr:graph1}). + $\BbbG = (S, \circ)$ в этом случае конструируется следующим образом. + Во-первых, придётся предположить, что $L$~--- множество с одним элементом, скажем $s$, и считать, что все рёбра помечены им% + \sidenote{А раз все рёбра имеют одинаковый заранее известный вес, то можно его и не писать для каждого ребра при задании графа. + Поэтому привычное нам изображение получается достаточно логичным.}. + Далее, $S = L \cup{\{n\}} = \{s,n\}$, где $n$~--- нейтральный элемент относительно $\circ$. + \marginnote{TODO: Здесь $n$~--- нейтральный из-за клэша с $e$ из алгебры?} + Тогда $\circ$ можно определить поточечно следующим образом. + \begin{itemize} + \item $s \circ s = s$ + \item $s \circ n = n \circ s = s$ + \item $n \circ n = n$ + \end{itemize} + + Таким образом, матрица смежности данного графа выглядит следующим образом: + \[ + \begin{pmatrix} + n & s & s & n \\ + s & n & s & n \\ + s & s & n & s \\ + n & n & s & n + \end{pmatrix}, + \] + что может показаться несколько непривычным. + Однако заметим, что построенная нами структура $\BbbG = (\{s,n\}, \circ)$ изоморфна $\BbbG' = (\{1,0\}, \lor)$. + При переходе к $\BbbG'$ мы получим привычную нам булеву матрицу смежности: + \[ + \begin{pmatrix} + 0 & 1 & 1 & 0 \\ + 1 & 0 & 1 & 0 \\ + 1 & 1 & 0 & 1 \\ + 0 & 0 & 1 & 0 + \end{pmatrix} + \] + Заметим, что матрица смежности неориентированного графа всегда симметрична относительно главной диагонали. +\end{example} + +\begin{marginfigure} + \caption{Ориентированный граф} + \label{gr:graph2} + \begin{center} + \input{figures/graph/graph2.tex} + \end{center} +\end{marginfigure} +\begin{example}[Пример матрицы смежности ориентированного графа] + \label{example:diGraph} + Дан ориентированный граф (см. рисунок \ref{gr:graph2}). + Построить его булеву матрицу смежности можно применив рассуждения из предыдущего примера (\ref{exmpl:undirectedGraphMatrix}) и выглядеть она будет следующим образом: + \[ + \begin{pmatrix} + 0 & 1 & 0 & 0 \\ + 0 & 0 & 1 & 0 \\ + 1 & 0 & 0 & 1 \\ + 0 & 0 & 1 & 0 + \end{pmatrix}. + \] +\end{example} + +\begin{marginfigure} + \caption{Помеченный граф} + \label{gr:graph3} + \begin{center} + \input{figures/graph/graph3.tex} + \end{center} +\end{marginfigure} +\begin{example}[Пример матрицы смежности помеченного графа] + Пусть дан помеченный граф (см. рисунок \ref{gr:graph3}). + В данном случае $L = \{\{a\},\{b\}\}$, а $\BbbG = ( \{\{a\},\{b\},\{a,b\},\varnothing\} ,\cup)$, где $\varnothing$~--- нейтральный элемент. + Тогда матрица матрица смежности исходного графа выглядит следующим образом: + \[ + \begin{pmatrix} + \varnothing & \{a\} & \varnothing & \varnothing \\ + \varnothing & \varnothing & \{a\} & \varnothing \\ + \{a\} & \varnothing & \varnothing & \{a,b\} \\ + \varnothing & \varnothing & \{b\} & \varnothing + \end{pmatrix}. + \] +\end{example} + +Необходимо заметить, что свойства структуры $\BbbG$, а значит и детали её построения, зависят от задачи, в рамках которой рассматривается граф. +В примерах выше мы строили $\BbbG$ из некоторых общих соображений, не специфицируя решаемую задачу, стараясь получить ожидаемый результат. +Далее мы рассмотрим пример, в котором видно, как решаемая задача влияет на построение $\BbbG$. + +\begin{marginfigure} + \caption{Взвешенный граф} + \label{gr:graph4} + \begin{center} + \input{figures/graph/graph4.tex} + \end{center} +\end{marginfigure} +\begin{example}[Пример матрицы смежности взвешенного графа] + \label{example:apspGraph} + \marginnote{TODO: Как по мне подписи для примеров излишни, потому что из их содержания легко понять о чём пример. } + Пусть дан взвешенный граф (см. рисунок \ref{gr:graph4}). + Будем считать, что веса берутся из $\BbbR$, а решаемая задача~--- поиск кратчайших путей между вершинами. + В таком случае естественно предположить, что для любой вершины $v_i$ существует петля $(v_i, 0, v_i)$, хоть она явно и не изображена. + Далее, $\BbbG = (\BbbR \cup \{+\infty\}, \min)$, где $+\infty$~--- нейтральный элемент относительно операции $\min$. + + В результате мы получим следующую матрицу смежности: + \[ + \begin{pmatrix} + 0 & -1.4 & \infty & \infty \\ + \infty & 0 & 2.2 & \infty \\ + 0.5 & \infty & 0 & 1.85 \\ + \infty & \infty & -0.76 & 0 + \end{pmatrix}. + \] +\end{example} + +Таким образом, уже можно заметить, что введение моноида как абстракции позволяет достаточно унифицированным образом смотреть на различные графы и их матрицы смежности. +Далее мы увидим, что данный путь позволит решать унифицированным образом достаточно широкий круг задач, связанных с анализом путей в графах. +Но сперва мы сформулируем различные варианты задачи поиска путей в графе. +% Это необходимо для формулировки задач, на решение которых мы в конечном итоге нацелены. + +\section{Обход графа в ширину} + +Обход графа в ширину (Breadth-First Search, BFS)~--- это одна из фундаментальных задач анализа графов, для решения которой существует соответствующий алгоритм, изложенный в классической литературе. +%(подробнее, например, в~\cite{} или~\cite{}). +Данный алгоритм является основой для многих алгоритмов поиска в графе. + +В общих чертах, задача заключается в том, чтобы начиная с некоторой заданной вершины графа (источника) обойти все достижимые из неё вершины в некотором порядке. +Шаг~--- просмотр все смежных. +И так для всего фронта. +Главное не посещать одну и ту же вершину несколько раз. + +Псевдокод классического алгоритма + +Пример. + +Алгоритм обхода в ширину может быть переформулирован в терминах матрично-векторных операций следующим образом% +\sidenote{ + Стоит отметить, что ситуация с не менее известным обходом в глубину (Depth-First Search, DFS) более сложная: на момент написания текста не известно естественного выражения данного обхода в терминах линейной алгебры. + Доказательство невозможности такого построения также не предъявлены. + При этом, решения для частных случаев (деревья, ориентированные графы без циклов) предложены, например, в работе~\cite{10.1145/3315454.3329962}.}. +Пусть фронт~--- вектор размера $n$, а сам граф представлен матрицей смежности. +Тогда один шаг~--- получение нового фронта~--- это умножение текущего фронта на матрицу смежности. +Для того, чтобы отслеживать посещённые вершины нужна маска. + +Псевдокод алгоритма на ЛА + +\begin{example} + + Рассмотрим обход в ширину графа из примера~\ref{example:diGraph} начиная с вершины 2. + Для обозначения текущего фронта будем использовать зелёный цвет, а для достижимых из него за один шаг~--- жёлтый, обведём вершину красным, если она посешается повторно. + \marginnote{TODO: Как по мне, так надо просто написать каждый шаг словами, и тогда станет сильно проще сверстать} + \begin{tabular}[t]{c | c} + \begin{minipage}[c]{0.35\textwidth} + \input{figures/graph/graph_BFS_1.tex} + \end{minipage} + & + \begin{minipage}{0.7\textwidth} + $\begin{aligned} + \emph{current\_front} & = + \begin{pmatrix} + 0 & 0 & 1 & 0 + \end{pmatrix} + \\ + \emph{visited} & = + \begin{pmatrix} + 0 & 0 & 0 & 0 + \end{pmatrix} + \\ + \emph{new\_front} & = + \emph{current\_front} \cdot M + \\ + & = + \begin{pmatrix} + 0 & 0 & 1 & 0 + \end{pmatrix} + \begin{pmatrix} + 0 & 1 & 0 & 0 \\ + 0 & 0 & 1 & 0 \\ + 1 & 0 & 0 & 1 \\ + 0 & 0 & 1 & 0 + \end{pmatrix} \\ + & = + \begin{pmatrix} + 1 & 0 & 0 & 1 + \end{pmatrix} + \\ + \emph{visited} & = \emph{visited} \emph{new\_front} \\ + & = + \begin{pmatrix} + 0 & 0 & 0 & 0 + \end{pmatrix} + \begin{pmatrix} + 0 & 0 & 1 & 0 + \end{pmatrix} + \\ + \emph{current\_front} & = \emph{visited} \emph{new\_front} + \\ + & = + \begin{pmatrix} + 1 & 0 & 0 & 1 + \end{pmatrix} + \begin{pmatrix} + 0 & 0 & 1 & 0 + \end{pmatrix} \\ + & = + \begin{pmatrix} + 1 & 0 & 0 & 1 + \end{pmatrix} \\ + \end{aligned}$ + \end{minipage} + \\ \hline + \begin{minipage}[c]{0.35\textwidth} + \input{figures/graph/graph_BFS_2.tex} + \end{minipage} + & + $\begin{aligned} + & \begin{pmatrix} + 1 & 0 & 0 & 1 + \end{pmatrix} + \begin{pmatrix} + 0 & 1 & 0 & 0 \\ + 0 & 0 & 1 & 0 \\ + 1 & 0 & 0 & 1 \\ + 0 & 0 & 1 & 0 + \end{pmatrix} \\ &= + \begin{pmatrix} + 0 & 1 & 1 & 0 + \end{pmatrix} + \end{aligned}$ + \\ \hline + \begin{minipage}[c]{0.35\textwidth} + \input{figures/graph/graph_BFS_3.tex} + \end{minipage} + & + $ + \begin{pmatrix} + 0 & 1 & 0 & 0 + \end{pmatrix} + \begin{pmatrix} + 0 & 1 & 0 & 0 \\ + 0 & 0 & 1 & 0 \\ + 1 & 0 & 0 & 1 \\ + 0 & 0 & 1 & 0 + \end{pmatrix} = + \begin{pmatrix} + 0 & 0 & 1 & 0 + \end{pmatrix} + $ + \end{tabular} + +\end{example} + + +multiple-source BFS. Тот же обход в ширину, только источников несколько и надо помнить, какая из вершин из какого источника достижима. Постановка задачи. Решение через линейную алгебру~\sidecite{9286186} Уже не вектор, а матрица: храним информацию про каждую стартовую вершину отдельно. + +Псевдокод алгоритма на ЛА + +Пример. + +\begin{minipage}[c]{0.35\textwidth} + \input{figures/graph/graph_MS-BFS_1.tex} +\end{minipage} +\begin{minipage}{0.7\textwidth} +\end{minipage} + + +\begin{minipage}[c]{0.35\textwidth} + \input{figures/graph/graph_MS-BFS_2.tex} +\end{minipage} +\begin{minipage}{0.7\textwidth} +\end{minipage} + + +\section{Задачи поиска путей} + +Одна из классических задач анализа графов~--- это задача поиска путей между вершинами с различными ограничениями. + +При этом возможны различные постановки задачи. +С одной стороны, постановки различаются тем, что именно мы хотим получить в качестве результата. Здесь наиболее частыми являются следующие варианты. + +\begin{itemize} + \item Наличие хотя бы одного пути, удовлетворяющего ограничениям, в графе. + В данном случае не важно, между какими вершинами существует путь, важно лишь наличие его в графе. + \item Наличие пути, удовлетворяющего ограничениям, между некоторыми вершинами: задача достижимости. + При данной постановке задачи, нас интересует ответ на вопрос достижимости вершины $v_i$ из вершины $v_j$ по пути, удовлетворяющему ограничениям. + Такая постановка требует лишь проверить существование пути, но не его предоставления в явном виде. + \item Поиск одного пути, удовлетворяющего ограничениям: необходимо не только установить факт наличия пути, но и предъявить его. + При этом часто подразумевается, что возвращается любой путь, являющийся решением, без каких-либо дополнительных ограничений. + Хотя, например, в некоторых задачах дополнительное требование простоты или наименьшей длины выглядит достаточно естественным. + \item Поиск всех путей: необходимо предоставить все пути, удовлетворяющие заданным ограничениям. +\end{itemize} + +С другой стороны, задачи могут различаться ещё и тем, как фиксируются множества стартовых и конечных вершин. +Здесь возможны следующие варианты: +\begin{itemize} + \item от одной вершины до всех, + \item между всеми парами вершин, + \item между фиксированной парой вершин, + \item между двумя множествами вершин $V_1$ и $V_2$, что подразумевает решение задачи для всех $(v_i,v_j) \in V_1 \times V_2$. +\end{itemize} + +Стоит отметить, что последний вариант является самым общим и остальные~--- лишь его частные случаи. +Однако этот вариант часто выделяют отдельно, подразумевая, что остальные, выделенные, варианты в него не включаются. + +В итоге, перебирая возможные варианты желаемого результата и способы фиксации стартовых и финальных вершин, мы можем сформулировать достаточно большое количество задач. +Например, задачу поиска всех путей между двумя заданными вершинами, задачу поиска одного пути от фиксированной стартовой вершины до каждой вершины в графе, или задачу достижимости между всеми парами вершин. + +Часто поиск путей сопровождается изучением их свойств, что далее приводит к формулированию дополнительных ограничений на пути в терминах этих свойств. +Например, можно потребовать, чтобы пути были простыми или не проходили через определённые вершины. +Один из естественных способов описывать свойства и, как следствие, задавать ограничения~--- это использовать ту алгебраическую структуру, из которой берутся веса рёбер графа% +\sidenote{На самом деле здесь наблюдается некоторая двойственность. + С одной стороны, действительно, удобно считать, что свойства описываются в терминах некоторой заданной алгебраической структуры. + Но, вместе с этим, структура подбирается исходя из решаемой задачи.}. + +Предположим, что дан граф $\mbfscrG = \langle V, E, L\rangle $, где $L = (S, \oplus, \otimes)$~--- это полукольцо. +Тогда изучение свойств путей можно описать следующим образом: +\begin{equation} + \label{eq:algPathProblem} + \left\{(v_i, v_j, c) \mid \exists v_i \pi v_j, c = \bigoplus_{\forall v_i \pi v_j} \bigotimes_{(u, l, v) \in \pi } l\right\}. +\end{equation} +\marginnote{TODO: В общем случае меня смущает forall множестве, по которому происходит бинарная операция} + +Иными словами, для каждой пары вершин, для которой существует хотя бы один путь, их соединяющий, мы агрегируем (с помощью операции $\oplus$ из полукольца) информацию обо всех путях между этими вершинами. +При этом информация о пути получается как свёртка меток рёбер пути с использованием операции $\otimes$\sidenote{Заметим, что детали свёртки вдоль пути зависят от свойств полукольца (и от решаемой задачи). + Так, если полукольцо коммутативно, то нам не обязательно соблюдать порядок рёбер. + В дальнейшем мы увидим, что данные особенности полукольца существенно влияют на особенности алгоритмов решения соответствующих задач.}. + +Естественным требованием (хотя бы для прикладных задач, решаемых таким способом) является существование и конечность указанной суммы. +На данном этапе мы не будем касаться того, какие именно свойства полукольца могут нам обеспечить данное свойство, однако в дальнейшем будем считать, что оно выполняется. +Более того, будем стараться приводить частные для конкретной задачи рассуждения, показывающие, почему это свойство выполняется в рассматриваемых в задаче ограничениях. + +Описанная выше задача общего вида называется анализом свойств путей алгебраическими методами (Algebraic Path Problem)~\sidecite{Baras2010PathPI} и предоставляет общий способ для решения широкого класса прикладных задач% +\sidenote{В работе \enquote{Path Problems in Networks}~\cite{Baras2010PathPI} собран действительно большой список прикладных задач с описанием соответствующих полуколец. + Сводная таблица на страницах 58--59 содержит 29 различных прикладных задач и соответствующих полуколец.}. +Наиболее известными являются такие задачи, как построение транзитивного замыкания графа и поиск кратчайших путей (All Pairs Shortest Path или APSP). +Далее мы подробнее обсудим эти две задачи и предложим алгоритмы их решения. + +\section{Алгоритм Флойда-Уоршелла} + +Наиболее естественным образом решение обсуждаемых выражается в терминах операций над матрицей смежности исходного графа. +Поэтому предположим, что исходный граф задан матрицей над моноидом $\BbbG = (S,\oplus)$. + +Как мы видели ранее, операция $\oplus$ позволяет нам агрегировать информацию по всем параллельным рёбрам. +Ровно она же и будет агрегировать информацию по всем путям между двумя вершинами% +\sidenote{Вообще говоря, работая с матрицей смежности мы не видим разницу между путём и ребром, так как любая запись в матрице смежности в ячейке $[i, j]$ говорит нам только о том, что вершины $i$ и $j$ связаны и эта связь обладает некоторым свойством (значение в ячейке), и ничего не говорит о том, как эта связь устроена.}. +Таким образом, осталось сконструировать операцию, отвечающую за агрегацию информации вдоль пути. +Здесь мы будем исходить из того, что новый путь может быть получен из двух подпутей, а свойство нового пути зависит только от свойств исходных подпутей. + +Таким образом, дополнительная операция, обозначим её $\otimes: S \times S \to S$% +\sidenote{При первом рассмотрении такой выбор кажется контринтуитивным. + Действительно, ведь при соединении путей мы как бы \enquote{складываем} их веса. + Но при более детальном анализе поведения этой операции, в частности, относительно нейтрального элемента, становится понятно, что она ведёт себя очень похоже на умножение. + Вероятно, стоит обратить внимание на операцию конкатенации, которая, с одной стороны, \enquote{делает то, что нам нужно}, а с другой, (и неспроста) часто обозначается $\cdot$.}% +, должна вести себя следующим образом. Пусть $S$~--- носитель моноида, $\Bbbzero \in S$~--- нейтральный элемент относительно $\oplus$. +\begin{itemize} + \label{itm:otimesIntro} + \item $s_1 \otimes s_2 = s_3$, $s_i \in S$, $s_i \neq \Bbbzero$: если существует путь $i \pi j$ со свойством $s_1$ и путь $j \pi k$ со свойством $s_2$, то существует путь $i \pi k$ со свойством $s_3$. + \item $s \otimes \Bbbzero = \Bbbzero$: если существует путь $i \pi j$ со свойством $s$ и не существует пути $j \pi k$, то не существует и пути $i \pi k$. + \item $\Bbbzero \otimes s = \Bbbzero$: если не существует пути $i \pi j$ и существует путь $j \pi k$ со свойством $s$, то не существует и пути $i \pi k$. + \item $\Bbbzero \otimes \Bbbzero = \Bbbzero$: если не существует пути $i \pi j$ и не существует пути $j \pi k$, то не существует и пути $i \pi k$. +\end{itemize} + +Новую операцию добавим к моноиду и получим новую алгебраическую структуру $\BbbG' = (S, \oplus,\otimes)$. +Данная структура является коммутативным моноидом по сложению (по построению) с нейтральным элементом $\Bbbzero$. +Из построения $\otimes$ видно, что $\Bbbzero$ является аннигилятором. +Ничего более про операцию $\otimes$, а значит и про $\BbbG'$ мы сказать, исходя из построения, не можем. +Классический фреймворк для решения algebraic path problem подразумевает, что $\BbbG'$ является полукольцом, однако далее мы увидим, что существуют задачи, в которых $\otimes$, например, не является ассоциативной% +\sidenote{Такой будет рассматриваемая в данной работе задача достижимости с ограничениями в терминах формальных языков. + Другие примеры можно найти в уже упоминавшейся работе~\cite{Baras2010PathPI}.}. +А значит, согласно нашему определению, $\BbbG'$ полукольцом не является. + +Теперь, когда построена алгебраическая структура, обеспечивающая вычисление формулы~ +\ref{eq:algPathProblem}, мы можем предложить алгоритм вычисления этой формулы и данным алгоритмом в интересующих нас частных случаях будет являться алгоритм Флойда-Уоршелла~\sidecite{Floyd1962, Bernard1959, Warshall1962}. +Псевдокод алгоритма представлен на листинге~\ref{lst:algoFloydWarshall}, а его сложность $O(n^3)$. +Он практически дословно основан на описанной выше идее сборки путей из двух подпутей: тройной вложенный цикл перебирает все возможные разбиения пути на две части, а в строке 7 как раз и происходит вычисление формулы~\ref{eq:algPathProblem}. + +Необходимо обратить внимание на несколько вещей. +Первая~--- порядок обхода. +Внешний цикл перебирает возможные точки разбиения (хотя мог бы, например, перебирать начальные вершины) для того, чтобы гарантировать правильный порядок вычисления подпутей (информация ни о каких подпутях не будет получена после того, как они поучаствовали в построении более длинного пути). +Вторая~--- количество итераций. +В данном случае мы ограничились тройным вложенным циклом от 0 до $n$ и для наших задач этого будет достаточно, однако, как доказательство этого факта, так и построение аналогичного алгоритма для других задач требует аккуратного анализа решаемой задачи и последующего доказательства корректности построенного алгоритма. + +% \begin{algorithm} +% \floatname{algorithm}{Listing} +% \begin{algorithmic}[1] +% \caption{Алгоритм Флойда-Уоршелла} +% \label{lst:algoFloydWarshall} +% \Function{FloydWarshall}{$\mbfscrG$} +% \State{$M \gets$ матрица смежности $\mbfscrG$} +% \Comment{Матрица над $\BbbG=(S,\oplus,\otimes)$} +% \State{$n \gets |V(\mbfscrG)|$} +% \For{k = 0; k < n; k++} +% \For{i = 0; i < n; i++} +% \For{j = 0; j < n; j++} +% \State{$M[i,j] \gets M[i,j] \oplus (M[i,k] \otimes M[k,j])$} +% \EndFor +% \EndFor +% \EndFor +% \State \Return $M$ +% \EndFunction +% \end{algorithmic} +% \end{algorithm} + +Хотя изначально данный алгоритм был предложен для решения задачи о кратчайших путях, при абстрагировании алгебраической структуры он превращается в алгоритм решения целого ряда задач. +В частности~--- нахождения транзитивного замыкания. +Так, если возьмём тропическое полукольцо $(\BbbR_{+\infty}, \min, +)$, то получим алгоритм для поиска кратчайших путей. +Если же возьмём булево полукольцо, то получим алгоритм для построения транзитивного замыкания графа. + +\begin{marginfigure} + \caption{Не полный граф} + \label{gr:graph2nottc} + \begin{center} + \input{figures/graph/graph2.tex} + \end{center} +\end{marginfigure} +\begin{marginfigure} + \caption{Полный граф} + \label{gr:graph5} + \begin{center} + \input{figures/graph/graph5.tex} + \end{center} +\end{marginfigure} +\begin{example}[Транзитивное замыкание графа] + \label{exmpl:transitiveClosure} + Пусть дан граф (см. рисунок~\ref{gr:graph2nottc}). + Его матрица смежности: + \[ + M = + \begin{pmatrix} + 0 & 1 & 0 & 0 \\ + 0 & 0 & 1 & 0 \\ + 1 & 0 & 0 & 1 \\ + 0 & 0 & 1 & 0 + \end{pmatrix}. + \] + + Здесь мы считаем, что отношение достижимости не рефлексивно: все диагональные элементы матрицы $M$ равны 0. + + Воспользовавшись алгоритмом из листинга~\ref{lst:algoFloydWarshall}, специализированного на случай булева полукольца, можно получить следующую матрицу смежности. + \[ + M' = + \begin{pmatrix} + 1 & 1 & 1 & 1 \\ + 1 & 1 & 1 & 1 \\ + 1 & 1 & 1 & 1 \\ + 1 & 1 & 1 & 1 + \end{pmatrix}. + \] + + А значит, транзитивным замыканием исходного графа является полный граф, изображенный на рисунке~\ref{gr:graph5}. +\end{example} + +Заметим, что рефлексивность отношения (значения элементов на главной диагонали матрицы смежности) непосредственно связана с особенностями решаемой задачи. +Например, если говорить о кратчайших расстояниях, то кажется естественным считать расстояние от вершины до самой себя равной нулю. +Однако для задачи транзитивного замыкания это уже не столь естественное предположение и часто отдельно говорят о рефлексивно-транзитивном замыкании, которое отдельно явным образом привносит рефлексивность (петли, диагональные элементы матрицы смежности). + +Аналогичным образом, используя данный алгоритм, но уже для тропического полукольца, можно решить задачу о поиске кратчайших путей для графа из примера~\ref{example:apspGraph}. + +Идеи, заложенные в алгоритме Флойда-Уоршелла, а также возможность абстрагировать его, помогут нам в дальнейшем предложить алгоритм для задачи достижимости с ограничениями в терминах формальных языков. + +\section{Анализ путей в графе и линейная алгебра} + +В данной главе мы рассмотрим некоторые связи% +\sidenote{Связь между графами и линейной алгеброй~--- обширная область, в которой можно даже выделить отдельные направления, такие как спектральная теория графов. + С точки зрения практики данная связь также подмечена давно и более полно с ней можно ознакомиться, например, в работах~\cite{doi:10.1137/1.9780898719918, Davis2018Algorithm9S}. + Кроме этого, много полезной информации можно найти на сайте \url{https://graphblas.github.io/GraphBLAS-Pointers/}.} +между графами и операциями над ними и матрицами и операциями над матрицами. + +Как мы видели, достаточно естественное представление графа~--- это его матрица смежности. +Далее можно заметить некоторое сходство между определением матричного умножения~\ref{def:MxM} и мыслями, которыми мы руководствовались, вводя операцию $\otimes$ (\ref{itm:otimesIntro}). +Действительно, пусть есть матрица $M$ размера $n \times n$ над $\BbbG = (S, \oplus, \otimes)$% +\sidenote{Здесь мы уже сталкиваемся с тем, что могут иметь смысл относительно экзотические алгебраические структуры. + Действительно, как мы выяснили, матрица смежности может быть определена на чем-то более бедным, чем полукольцо, а матричное умножение мы определяли над полукольцом. + Но если задуматься, то и для определения произведения матриц полукольцо вовсе необязательно, достаточно более бедной структуры.}~--- матрица смежности графа. +Умножим её саму на себя: вычислим $M'= M \cdot M$. +Тогда, по~\ref{def:MxM}, $M'[i, j] = \bigoplus_{l \in [0 \rng n-1]} M[i, l] \otimes M[l, j]$. +Размер $M'$ также $n \times n$. +То есть $M'$ задаёт такой граф, что в нём будет путь со свойством, являющимся агрегацией свойств всех путей, составленных из двух подпутей в исходном графе. +А именно, если в исходном графе есть путь из $i$ в $l$ с некоторым свойством (его значение хранится в $M[i, l]$), и был путь из $l$ в $j$ (его значение хранится в $M[l,j]$), то в новом графе свойство $M[i, l] \otimes M[l, j]$ аддитивно (используя $\oplus$) учтётся в свойстве пути из $i$ в $j$. + +Таким образом, произведение матриц смежности соответствует обработке информации о путях интересующим нас образом. +Это наблюдение позволяет предложить решение задач анализа свойств путей, основанное на операциях над матрицами. +Рассмотрим такое решение для задачи о кратчайших путях. + +Пусть $D_k$~--- матрица кратчайших путей, состоящих не более чем из $k$ рёбер. +То есть $D_k[i, j]$~--- это длина кратчайшего пути из вершины $i$ в вершину $j$, такого, что он состоит не более чем из $k$ ребер. +Если такого пути нет, то $D_k[i, j] = +\infty$. + +Таким образом, $D_1 = M$, где $M$~--- это матрица смежности исходного графа, а решением APSP является $D_{n-1}$, вычисляемая с помощью следующего рекуррентного соотношения: +\begin{gather*} + D(1) = M \\ + D(2) = D(1) \cdot M = M^2 \\ + D(3) = D(2) \cdot M = M^3 \\ + \vdots \\ + D(n - 1) = D(n - 2) \cdot M = M^{(n - 1)} +\end{gather*} + +Здесь мы пользуемся той особенностью задачи, что кратчайший путь в ориентированном графе (без отрицательных циклов) не может быть длиннее $n$% +\sidenote{Раз отрицательных циклов нету, то проходить через одну вершину, коих $n$, больше одного раза бессмысленно.}. +Более того, мы пользуемся тем, что используемая структура именно полукольцо, а исходное отношение рефлексивно% +\sidenote{ + Тот факт, что в любой вершине есть петля с весом 0, а 0~--- нейтральный для $\otimes$, позволяет не суммировать матрицы. + Итоговая матрица содержит данные о путях длины \emph{не больше чем} вычисляемая степень, хотя должна бы содержать данные о путях ровно и только такой длины. + Предлагается самостоятельно исследовать данный феномен.}. + +Таким образом, решение APSP сведено к произведению матриц над тропическим полукольцом, однако вычислительная сложность решения слишком большая: $O(n K(n))$, где $K(n)$~--- сложность алгоритма умножения матриц. + +Чтобы улучшить сложность, заметим, что, например, $D_3$ вычислять не обязательно, так как можно сразу вычислить $D_4$ как $D_2 \cdot D_2$. + +В итоге получим следующую последовательность вычислений: +\begin{gather*} + D_1 = M \\ + D_2 = M^2 = M \cdot M \\ + D_4 = M^4 = M^2 \cdot M^2 \\ + D_8 = M^8 = M^4 \cdot M^4 \\ + \vdots \\ + D_{2^{\log(n-1)}} = M^{2^{\log(n-1)}} = M^{2^{\log(n-1)} - 1} \cdot M^{2^{\log(n-1)} - 1} \\ + D_{n-1} = D_{2^{\log(n-1)}} +\end{gather*} + +Теперь вместо $n$ итераций нам нужно $\log{n}$, а итоговая сложность решения~--- $O(\log{n} K(n))$% +\sidenote{ + Заметим, что это оценка для худшего случая. + На практике при использовании данного подхода можно прекращать вычисления как только при двух последовательных шагах получились одинаковые матрицы ($D_i = D_{i-1}$). + Это приводит нас к понятию \emph{неподвижной точки}, обсуждение которого лежит за рамками повествования.}. +Данный алгоритм называется \emph{repeated squaring}% +\sidenote{Пример решения APSP с помощью repeated squaring: \url{http://users.cecs.anu.edu.au/~Alistair.Rendell/Teaching/apac_comp3600/module4/all_pairs_shortest_paths.xhtml}}. +Здесь мы предполагаем, что $n-1 = 2^k$ для какого-то $k$. +На практике такое верно далеко не всегда. +Если это условие не выполняется, то необходимо взять ближайшую сверху степень двойки% +\sidenote{ + Кажется, что это приведёт к избыточным вычислениям. + Попробуйте оценить, на сколько много лишних вычислений будет сделано в худшем случае.}. + +Таким образом, APSP сводится к умножению матриц над полукольцом, что, к сожалению, не позволяет этим путём получить истинно субкубический алгоритм для задачи. +Тем не менее, позволяет получить слегка субкубический. +Приведем некоторые работы по APSP для ориентированных графов с вещественными весами (здесь $n$~--- количество вершин в графе), по которым можно более детально ознакомиться как с историей вопроса, так и с текущими результатами: +\begin{itemize} + \item M.L. Fredman (1976)~--- $O(n^3(\log \log n / \log n)^\frac{1}{3})$~--- использование дерева решений~\sidecite{FredmanAPSP1976} + \item W. Dobosiewicz (1990)~--- $O(n^3 / \sqrt{\log n})$~--- использование операций на Word Random Access Machine~\sidecite{Dobosiewicz1990} + \item T. Takaoka (1992)~--- $O(n^3 \sqrt{\log \log n / \log n})$~--- использование таблицы поиска~\sidecite{Takaoka1992} + \item Y. Han (2004)~--- $O(n^3 (\log \log n / \log n)^\frac{5}{7})$~\sidecite{Han2004} + \item T. Takoaka (2004)~--- $O(n^3 (\log \log n)^2 / \log n)$~\sidecite{Takaoka2004} + \item T. Takoaka (2005)~--- $O(n^3 \log \log n / \log n)$~\sidecite{Takaoka2005} + \item U. Zwick (2004)~--- $O(n^3 \sqrt{\log \log n} / \log n)$~\sidecite{Zwick2004} + \item T.M. Chan (2006)~--- $O(n^3 / \log n)$~--- многомерный принцип \enquote{разделяй и властвуй}~\sidecite{Chan2008} +\end{itemize} + +Вопрос же о истинно субкубических алгоритмах решения APSP всё ещё открыт~\sidecite{Chan2010} и активно обсуждается в научном сообществе. + +Аналогичным образом можно свести транзитивное замыкание к матричным операциям. +Предлагаем проделать это самостоятельно, заодно обратив внимание на важность рефлексивности (в примере~\ref{exmpl:transitiveClosure} её нет). + +Заметим, что оптимизация, связанная с возведением в квадрат возможна только при ассоциативности произведения матриц, что зависит от свойств алгебраической структуры, над которой построены матрицы. +Для полукольца такая оптимизация законна, однако в некоторых случаях её применить нельзя. +Таким случаем как раз и будет рассматриваемая в нашей работе задача. +Поэтому построение алгоритма её решения через операции над матрицами, хотя и будет основано на указанных выше соображениях, но будет сопряжено с некоторыми трудностями. + +%\section{Вопросы и задачи} +%\begin{enumerate} +% \item Реализуйте абстракцию полукольца, позволяющую конструировать полукольца с произвольными операциями. +% \item Реализуйте алгоритм произведения матриц над произвольным полукольцом. Используйте результат решения предыдущей задачи. +% \item Используя результаты предыдущих задач, реализуйте алгоритм построения транзитивного замыкания через произведение матриц. +% \item Используя результаты предыдущих задач, реализуйте алгоритм решения задачи APSP для ориентированного через произведение матриц. +% \item Используя существующую библиотеку линейной алгебры для CPU, решите задачу построения транзитивного замыкания графа. +% \item Используя существующую библиотеку линейной алгебры для CPU, решите задачу APSP для ориентированного графа. +% \item Используя существующую библиотеку линейной алгебры для GPGPU, решите задачу построения транзитивного замыкания графа. +% \item Используя существующую библиотеку линейной алгебры для GPGPU, решите задачу APSP для ориентированного графа. +% \item Сравните произволительность решений предыдущих задач +%\end{enumerate} diff --git a/tex/Introduction.tex b/tex/Introduction.tex index ece901c..a09893b 100644 --- a/tex/Introduction.tex +++ b/tex/Introduction.tex @@ -48,6 +48,7 @@ %Все главы, начиная с~\ref{chpt:GraphTheoryIntro}, снабжены списком вопросов и задач для самостоятельного решения и закрепления материала. \begin{figure*} + \caption{Структура данной книги} \begin{center} \begin{tikzpicture}[shorten >= 1pt, auto, @@ -83,5 +84,4 @@ (q_flpq) edge (q_mcfpq); \end{tikzpicture} \end{center} - \caption{Структура данной книги} \end{figure*} diff --git a/tex/LinearAlgebra.tex b/tex/LinearAlgebra.tex index d16e7b1..2f2774f 100644 --- a/tex/LinearAlgebra.tex +++ b/tex/LinearAlgebra.tex @@ -216,15 +216,15 @@ \section{Группа} \begin{example} Рассмотрим несколько примеров групп. \begin{itemize} - \item Целые числа $\Z$ с операцией сложения $+$ являются группой. + \item Целые числа $\BbbZ$ с операцией сложения $+$ являются группой. Получается дополнением моноида из предыдущего раздела обратными по сложению элементами. - \item Целые числа $\Z$ без нуля% + \item Целые числа $\BbbZ$ без нуля% \sidenote{ При наличии нуля возникают трудности с нейтральным элементом. Логично считать $1$ нейтральным по умножению, однако $0 \cdot 1 = 0$, а не 1, как того требует определение.} с операцией умножения $\cdot$ не являются группой, так как нет обратных по умножению. - Действительно, возьмём $a = 3$, тогда должен существовать $a^{-1} \in \Z$, такой что $3 \cdot a^{-1} = 1$. - Видим, что $a^{-1} = 1/3$, но $1/3 \notin \Z$. + Действительно, возьмём $a = 3$, тогда должен существовать $a^{-1} \in \BbbZ$, такой что $3 \cdot a^{-1} = 1$. + Видим, что $a^{-1} = 1/3$, но $1/3 \notin \BbbZ$. \item Множество обратимых% \sidenote{ Квадратная матрица $M$ называется обратимой, если существует матрица $N$, называемая обратной, такая что $M \cdot N = N \cdot M = I$, где $I$~--- единичная матрица. @@ -238,25 +238,25 @@ \section{Полукольцо} \begin{definition}[Полукольцо] Непустое множество $R$ с двумя бинарными операциями $\oplus: R \times R \to R$ (часто называют сложением) и $\otimes: R \times R \to R$ (часто называют умножением) называется \emph{полукольцом}, если выполнены следующие условия. \begin{enumerate} - \item $(R, \oplus)$~--- это коммутативный моноид, нейтральный элемент которого~--- $\bz$. Для любых $a, b, c \in R$: + \item $(R, \oplus)$~--- это коммутативный моноид, нейтральный элемент которого~--- $\Bbbzero$. Для любых $a, b, c \in R$: \begin{itemize} \item $(a \oplus b) \oplus c = a \oplus (b \oplus c)$ - \item $\bz \oplus a = a \oplus \bz = a$ + \item $\Bbbzero \oplus a = a \oplus \Bbbzero = a$ \item $a \oplus b = b \oplus a$ \end{itemize} - \item $(R, \otimes)$~--- это моноид, нейтральный элемент которого~--- $\bo$. Для любых $a, b, c \in R$: + \item $(R, \otimes)$~--- это моноид, нейтральный элемент которого~--- $\Bbbzero$. Для любых $a, b, c \in R$: \begin{itemize} \item $(a \otimes b) \otimes c = a \otimes (b \otimes c)$ - \item $\bo \otimes a = a \otimes \bo = a$ + \item $\Bbbzero \otimes a = a \otimes \Bbbzero = a$ \end{itemize} \item $\otimes$ дистрибутивно слева и справа относительно $\oplus$: \begin{itemize} \item $a \otimes (b \oplus c) = (a \otimes b) \oplus (a \otimes c)$ \item $(a \oplus b) \otimes c = (a \otimes c) \oplus (b \otimes c)$ \end{itemize} - \item $\bz$ является \emph{аннигилятором} по умножению: + \item $\Bbbzero$ является \emph{аннигилятором} по умножению: \begin{itemize} - \item для любых $a \in R$ выполнено $\bz \otimes a = a \otimes \bz = \bz$ + \item для любых $a \in R$ выполнено $\Bbbzero \otimes a = a \otimes \Bbbzero = \Bbbzero$ \end{itemize} \end{enumerate} Если операция $\otimes$ коммутативна, то говорят о \emph{коммутативном полукольце}. @@ -321,20 +321,20 @@ \section{Кольцо} \begin{definition}[Кольцо] Непустое множество $R$ с двумя бинарными операциями $\oplus: R \times R \to R$ (умножение) и $\otimes: R \times R \to R$ (сложение) называется \emph{кольцом}, если выполнены следующие условия. \begin{enumerate} - \item $(R, \oplus)$~--- это абелева группа, нейтральный элемент которой~--- $\bz$. + \item $(R, \oplus)$~--- это абелева группа, нейтральный элемент которой~--- $\Bbbzero$. Для любых $a, b, c \in R$: \begin{itemize} \item $(a \oplus b) \oplus c = a \oplus (b \oplus c)$ - \item $\bz \oplus a = a \oplus \bz = a$ + \item $\Bbbzero \oplus a = a \oplus \Bbbzero = a$ \item $a \oplus b = b \oplus a$ - \item для любого $a \in R$ существует $-a \in R$, такой что $a + (-a) = \bz$. + \item для любого $a \in R$ существует $-a \in R$, такой что $a + (-a) = \Bbbzero$. \end{itemize} В последнем пункте кроется отличие от полукольца. - \item $(R, \otimes)$~--- это моноид, нейтральный элемент которого~--- $\bo$. + \item $(R, \otimes)$~--- это моноид, нейтральный элемент которого~--- $\Bbbzero$. Для любых $a, b, c \in R$: \begin{itemize} \item $(a \otimes b) \otimes c = a \otimes (b \otimes c)$ - \item $\bo \otimes a = a \otimes \bo = a$ + \item $\Bbbzero \otimes a = a \otimes \Bbbzero = a$ \end{itemize} \item $\otimes$ дистрибутивно слева и справа относительно $\oplus$: \begin{itemize} @@ -344,24 +344,24 @@ \section{Кольцо} \end{enumerate} \end{definition} -Заметим, что мультипликативное свойство $\bz$ (быть аннигилятором по умножению) не указыватеся явно, так как может быть выведено из остальных утверждений. +Заметим, что мультипликативное свойство $\Bbbzero$ (быть аннигилятором по умножению) не указыватеся явно, так как может быть выведено из остальных утверждений. Действительно, \begin{enumerate} - \item $a \otimes \bz = a \otimes (\bz \oplus \bz)$, так как $\bz$~--- нейтральный по сложению, то $\bz \oplus \bz = \bz$ - \item Воспользуемся дистрибутивностью: $a \otimes (\bz \oplus \bz) = a \otimes \bz \oplus a \otimes \bz$. - В итоге: $a \otimes \bz = a \otimes \bz \oplus a \otimes \bz$ - \item Так как у нас есть группа по сложению, то для любого $a$ существует обратный элемент $a^{-1}$, $a \oplus a^{-1} = \bz$. - Прибавим $a^{-1} \otimes \bz$ к левой и правой части равенства% + \item $a \otimes \Bbbzero = a \otimes (\Bbbzero \oplus \Bbbzero)$, так как $\Bbbzero$~--- нейтральный по сложению, то $\Bbbzero \oplus \Bbbzero = \Bbbzero$ + \item Воспользуемся дистрибутивностью: $a \otimes (\Bbbzero \oplus \Bbbzero) = a \otimes \Bbbzero \oplus a \otimes \Bbbzero$. + В итоге: $a \otimes \Bbbzero = a \otimes \Bbbzero \oplus a \otimes \Bbbzero$ + \item Так как у нас есть группа по сложению, то для любого $a$ существует обратный элемент $a^{-1}$, $a \oplus a^{-1} = \Bbbzero$. + Прибавим $a^{-1} \otimes \Bbbzero$ к левой и правой части равенства% \sidenote{Обычно данное действие воспринимается как очевидное, но, строго говоря, оно требует аккуратного введения структур с равенством и соответствующих аксиом.}% , полученного на предыдущем шаге: - \[a \otimes \bz \oplus a^{-1} \otimes \bz = a \otimes \bz \oplus a \otimes \bz \oplus a^{-1} \otimes \bz.\] + \[a \otimes \Bbbzero \oplus a^{-1} \otimes \Bbbzero = a \otimes \Bbbzero \oplus a \otimes \Bbbzero \oplus a^{-1} \otimes \Bbbzero.\] \item Воспользуемся дистрибутивностью и ассоциативностью. \begin{align*} - (a \oplus a^{-1}) \otimes \bz & = a \otimes \bz \oplus (a \oplus a^{-1}) \otimes \bz \\ - \bz \otimes \bz & = a \otimes \bz \oplus \bz \otimes \bz \\ - \bz & = a \otimes \bz + (a \oplus a^{-1}) \otimes \Bbbzero & = a \otimes \Bbbzero \oplus (a \oplus a^{-1}) \otimes \Bbbzero \\ + \Bbbzero \otimes \Bbbzero & = a \otimes \Bbbzero \oplus \Bbbzero \otimes \Bbbzero \\ + \Bbbzero & = a \otimes \Bbbzero \end{align*} - \item Аналогично можно доказать, что $\bz = \bz \otimes a$. + \item Аналогично можно доказать, что $\Bbbzero = \Bbbzero \otimes a$. \end{enumerate} %\section{Поле} diff --git a/tex/figures/graph/graph0.tex b/tex/figures/graph/graph0.tex new file mode 100644 index 0000000..f305249 --- /dev/null +++ b/tex/figures/graph/graph0.tex @@ -0,0 +1,19 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5 of q_2] {$3$}; + \path[->] + (q_0) edge[left] node {a} (q_1) + (q_1) edge[above] node {a} (q_2) + (q_2) edge[below] node {a} (q_0) + (q_2) edge[bend left, above] node {b} (q_3) + (q_3) edge[bend left, below] node {b} (q_2); +\end{tikzpicture} diff --git a/tex/figures/graph/graph1.tex b/tex/figures/graph/graph1.tex new file mode 100644 index 0000000..322700d --- /dev/null +++ b/tex/figures/graph/graph1.tex @@ -0,0 +1,18 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[] + (q_0) edge (q_1) + (q_1) edge (q_2) + (q_2) edge (q_0) + (q_2) edge (q_3); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph2.tex b/tex/figures/graph/graph2.tex new file mode 100644 index 0000000..1605ccb --- /dev/null +++ b/tex/figures/graph/graph2.tex @@ -0,0 +1,19 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge (q_1) + (q_1) edge (q_2) + (q_2) edge (q_0) + (q_2) edge [bend left] (q_3) + (q_3) edge [bend left] (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph3.tex b/tex/figures/graph/graph3.tex new file mode 100644 index 0000000..780b751 --- /dev/null +++ b/tex/figures/graph/graph3.tex @@ -0,0 +1,20 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge[left] node {$\{a\}$} (q_1) + (q_1) edge[above] node {$\{a\}$} (q_2) + (q_2) edge[below] node {$\{a\}$} (q_0) + (q_2) edge[bend left = 15, above] node {$\{a\}$} (q_3) + (q_2) edge[bend left = 65, above] node {$\{b\}$} (q_3) + (q_3) edge[bend left, below] node {$\{b\}$} (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph4.tex b/tex/figures/graph/graph4.tex new file mode 100644 index 0000000..5462c98 --- /dev/null +++ b/tex/figures/graph/graph4.tex @@ -0,0 +1,19 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge[left] node {$-1.4$} (q_1) + (q_1) edge[above] node[yshift=5pt] {$2.2$} (q_2) + (q_2) edge[below] node[yshift=-5pt] {$0.5$} (q_0) + (q_2) edge[bend left, above] node {$1.85$} (q_3) + (q_3) edge[bend left, below] node {$-0.76$} (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph5.tex b/tex/figures/graph/graph5.tex new file mode 100644 index 0000000..75fa0fd --- /dev/null +++ b/tex/figures/graph/graph5.tex @@ -0,0 +1,31 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge[loop below] node {} () + edge node {} (q_1) + edge[bend right] node {} (q_2) + edge[bend right = 55] node {} (q_3) + (q_1) edge[loop above] node {} () + edge[bend right] node {} (q_0) + edge node {} (q_2) + edge[bend left = 55, above] node {} (q_3) + (q_2) edge[loop below] node {} () + edge[bend right] node {} (q_1) + edge node {} (q_0) + edge[bend left, above] node {} (q_3) + (q_3) edge[loop above] node {} () + edge[bend left, below] node {} (q_2) + edge[bend left, below] node {} (q_0) + edge[bend right, below] node {} (q_1) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph_BFS_1.tex b/tex/figures/graph/graph_BFS_1.tex new file mode 100644 index 0000000..2e142de --- /dev/null +++ b/tex/figures/graph/graph_BFS_1.tex @@ -0,0 +1,19 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state,fill=yellow] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state,fill=green] (q_2) at (T60.apex) {$2$}; + \node[state,fill=yellow] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge (q_1) + (q_1) edge (q_2) + (q_2) edge (q_0) + (q_2) edge [bend left] (q_3) + (q_3) edge [bend left] (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph_BFS_2.tex b/tex/figures/graph/graph_BFS_2.tex new file mode 100644 index 0000000..62fe9f2 --- /dev/null +++ b/tex/figures/graph/graph_BFS_2.tex @@ -0,0 +1,19 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state,fill=green] (q_0) at (T60.right corner) {$0$}; + \node[state,fill=yellow] (q_1) at (T60.left corner) {$1$}; + \node[state,fill=yellow, draw=red, line width=0.45mm] (q_2) at (T60.apex) {$2$}; + \node[state,fill=green] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge (q_1) + (q_1) edge (q_2) + (q_2) edge (q_0) + (q_2) edge [bend left] (q_3) + (q_3) edge [bend left] (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph_BFS_3.tex b/tex/figures/graph/graph_BFS_3.tex new file mode 100644 index 0000000..3c581b8 --- /dev/null +++ b/tex/figures/graph/graph_BFS_3.tex @@ -0,0 +1,19 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state,fill=green] (q_1) at (T60.left corner) {$1$}; + \node[state,fill=yellow, draw=red, line width=0.45mm] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge (q_1) + (q_1) edge (q_2) + (q_2) edge (q_0) + (q_2) edge [bend left] (q_3) + (q_3) edge [bend left] (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph_MS-BFS_1.tex b/tex/figures/graph/graph_MS-BFS_1.tex new file mode 100644 index 0000000..01ffb89 --- /dev/null +++ b/tex/figures/graph/graph_MS-BFS_1.tex @@ -0,0 +1,19 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state,fill=green] (q_1) at (T60.left corner) {$1$}; + \node[state,fill=yellow] (q_2) at (T60.apex) {$2$}; + \node[state,fill=green] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge (q_1) + (q_1) edge (q_2) + (q_2) edge (q_0) + (q_2) edge [bend left] (q_3) + (q_3) edge [bend left] (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/graph_MS-BFS_2.tex b/tex/figures/graph/graph_MS-BFS_2.tex new file mode 100644 index 0000000..6360763 --- /dev/null +++ b/tex/figures/graph/graph_MS-BFS_2.tex @@ -0,0 +1,19 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state,fill=yellow] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state,fill=green] (q_2) at (T60.apex) {$2$}; + \node[state,fill=yellow, draw=red, line width=0.45mm] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge (q_1) + (q_1) edge (q_2) + (q_2) edge (q_0) + (q_2) edge [bend left] (q_3) + (q_3) edge [bend left] (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/graph/path0.tex b/tex/figures/graph/path0.tex new file mode 100644 index 0000000..3e46fb2 --- /dev/null +++ b/tex/figures/graph/path0.tex @@ -0,0 +1,6 @@ +\begin{tikzpicture}[on grid, auto] + \node[state] (v_0) {$v_0$}; + \node[state] (v_n) [right=2 of v_0] {$v_n$}; + \path[->] + (v_0) edge [out=45] node {$\pi$} (v_n); +\end{tikzpicture} diff --git a/tex/main.tex b/tex/main.tex index a93cdd2..fc04112 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -2,7 +2,7 @@ fontsize=10pt, a4paper, twoside=false, - parskip=false + parskip=false, ]{kaobook} \input{styles/language.tex} @@ -44,6 +44,7 @@ \pagelayout{margin} % Restore margins \input{LinearAlgebra} +\input{GraphTheoryIntro} \backmatter \setchapterstyle{plain} diff --git a/tex/styles/math.tex b/tex/styles/math.tex index 53c8cfb..0610eb4 100644 --- a/tex/styles/math.tex +++ b/tex/styles/math.tex @@ -2,7 +2,3 @@ \usepackage{nicematrix} % \setmathfont[range={\doubleplus}, Scale=MatchLowercase]{Asana Math} - -\NewDocumentCommand{\Z}{}{\mathbb{Z}} -\NewDocumentCommand{\bz}{}{\mathbb{0}} % Bold zero -\NewDocumentCommand{\bo}{}{\mathbb{1}} % Bold one diff --git a/tex/styles/tikz.tex b/tex/styles/tikz.tex index 34609f5..704f667 100644 --- a/tex/styles/tikz.tex +++ b/tex/styles/tikz.tex @@ -2,9 +2,10 @@ \usetikzlibrary{arrows.meta} \usetikzlibrary{external} \usetikzlibrary{positioning} +\usetikzlibrary{shapes.geometric} +\usetikzlibrary{automata} \tikzsetexternalprefix{figures/externalized/} -% \usetikzlibrary{fit, calc, automata} -% \usetikzlibrary{shapes.geometric} +% \usetikzlibrary{fit, calc} % \usetikzlibrary{decorations.pathmorphing} From 9f26332556dfd47d6d816e04aeb1cbc4c3cbd6e1 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Sun, 16 Jun 2024 22:09:21 +0300 Subject: [PATCH 19/29] Add Formal Language Theory Intro chapter --- tex/FormalLanguageTheoryIntro.tex | 310 ++++++++++++++++++++++++++++++ tex/figures/Chomsky.pdf | Bin 0 -> 14109 bytes tex/figures/Chomsky.svg | 115 +++++++++++ tex/main.tex | 5 +- 4 files changed, 429 insertions(+), 1 deletion(-) create mode 100644 tex/FormalLanguageTheoryIntro.tex create mode 100644 tex/figures/Chomsky.pdf create mode 100644 tex/figures/Chomsky.svg diff --git a/tex/FormalLanguageTheoryIntro.tex b/tex/FormalLanguageTheoryIntro.tex new file mode 100644 index 0000000..5e1c829 --- /dev/null +++ b/tex/FormalLanguageTheoryIntro.tex @@ -0,0 +1,310 @@ +\setchapterpreamble[u]{\margintoc} +\chapter{Общие сведения теории формальных языков} +\label{chpt:FormalLanguageTheoryIntro} + +В данной главе мы рассмотрим основные понятия из теории формальных языков, которые пригодятся нам в дальнейшем изложении. +Заметим, что мы рассмотрим лишь те результаты теории формальных языков,которые будут необходимы нам для дальнейшего изложения. +Для более глубокого изучения именно теории формальных языков рекомендуется обратиться к классической литературе. +Например, к работам Харрисона~\cite{10.5555/578595}, Хопкрофта~\cite{hopcroft2001introduction} или другой подобной литературе. +\marginnote[*2]{ + В рамках данной работы мы будем говорить о \enquote{типичных} языках, элементами которых являются объекты, максимально похожие на строки. + При этом будет оставлен за бортом тот факт, что базовое определение позволяет нам рассматривать в качестве \enquote{строительных элементов} (алфавита) практически произвольные объекты, а значит, создавать весьма нетривиальные конструкции в качестве слов языка. + Примерами \enquote{нестроковых} языков могут послужить языки деревьев~\cite{tata2007} или языки графов~\cite{EHRIG1992557, Courcelle2009}. +} + +\begin{definition}[Алфавит] + \emph{Алфавит}~--- это конечное множество. + Элементы этого множества будем называть \emph{символами}. +\end{definition} + +\begin{example} + Примеры алфавитов. + \begin{itemize} + \item Латинский алфавит $\Sigma = \{a, b, c, \dots, z\}$. + \item Кириллический алфавит $\Sigma = \{\text{а, б, в, \dots, я}\}$. + \item Алфавит натуральных чисел в шестнадцатеричной записи + \[\Sigma = \{0, 1, 2, 3, 4, 5, 6, 7 ,8, 9, A, B, C, D, E, F\}.\] + \end{itemize} +\end{example} + +Традиционное обозначение для алфавита~--- $\Sigma$. +Также мы будем использовать различные прописные буквы латинского алфавита. +Для обозначения символов алфавита будем использовать строчные буквы латинского алфавита: $a, b, \dots, x, y, z$. + +Будем считать, что над алфавитом $\Sigma$ всегда определена операция конкатенации $\cdot: \Sigma^* \times \Sigma^* \to \Sigma^*$. +\marginnote{TODO: объяснить звездочку Клини} +При записи выражений символ точки (обозначение операции конкатенации) часто будем опускать: $a \cdot b = ab$. + +\begin{definition}[Слово] + \emph{Слово} над алфавитом $\Sigma$~--- это конечная конкатенация символов алфавита $\Sigma$: $\omega = a_0 \cdot a_1 \cdot \dots \cdot a_m$, где $\omega$~--- слово, а $a_i \in \Sigma$ для любого $i$. + Для обозначения пустого слова (слова, содержащего ноль символов) будем использовать специальный символ $\varepsilon, \varepsilon \notin \Sigma$. +\end{definition} + +\begin{definition}[Длина слова] + Пусть $\omega = a_0 \cdot a_1 \cdot \dots \cdot a_m$~--- слово над алфавитом $\Sigma$. + Будем называть $m + 1$ \emph{длиной слова} и обозначать как $|\omega|$. + Длина пустого слова равна нулю. +\end{definition} + +\begin{definition}[Количество вхождений символа] + Пусть $\omega$~--- слово над алфавитом $\Sigma$. Пусть $t \in \Sigma$~--- некоторый символ из алфавита. + Тогда будем обозначать количество вхождений символа $t$ в слове $\omega$ как $|\omega|_t$. +\end{definition} + +\begin{definition}[Язык] + \emph{Язык} над алфавитом $\Sigma$~--- это множество слов над алфавитом $\Sigma$. +\end{definition} + +\begin{example} + Примеры языков. + + \begin{itemize} + \item Язык целых чисел в двоичной записи $\{0, 1, -1, 10, 11, -10, -11, \dots\}$. + \marginnote{TODO: Меня смущает - перед бинарными числами} + \item Язык всех правильных скобочных последовательностей + \[\{(), (()), ()(), (())(), \dots\}.\] + \end{itemize} +\end{example} + +Любой язык над алфавитом $\Sigma$ является подмножеством универсального множества $\Sigma^*$~--- множества всех слов над алфавитом $\Sigma$. + +Заметим, что язык не обязан быть конечным множеством, в то время как алфавит в нашей области всегда конечен% +\sidenote{Существуют ситуации, когда возникают бесконечные алфавиты.} +и изучаем мы конечные слова% +\sidenote{ + Существуют ситуации, когда возникают бесконечные слова. + Например работы по обработке потоков. +}. + +Можно выделить следующие основные \emph{способы задания языков}. +\begin{itemize} + \item Перечислить все элементы. + Такой способ работает только для конечных языков. + Перечислить бесконечное множество за конечное время не получится. + \item Задать генератор~--- процедуру, которая возвращает очередное слово языка. + \item Задать распознаватель~--- процедуру, которая по данному слову может определить, принадлежит оно заданному языку или нет. +\end{itemize} + +Стоит отметить, что существуют и другие способы задания. +Например, язык может определяться как решение некоторого \emph{языкового уравнения}~\sidecite{Leiss1999}. + +\section{Теоретико-множественные операции над языками} + +Так как язык~--- это \emph{множество} слов, то над языками естественным образом определены теоретико-множественные операции, такие как объединение, пересечение, дополнение. +\begin{itemize} + \item $L_1 \cup L_2 = \{ \omega \mid \omega \in L_1 \text{ или } \omega \in L_2\}$ + \item $L_1 \cap L_2 = \{ \omega \mid \omega \in L_1 \text{ и } \omega \in L_2\}$ + \item $\overline{L} = \{ \omega \mid \omega \in \Sigma^* \text{ и } \omega \notin L\}$, где $L$~--- язык над алфавитом $\Sigma$ . +\end{itemize} + +Но кроме этого, нам потребуются и относительно специальные операции, определённые ниже. + +\begin{definition}[TODO: Что ты такое] + Пусть дано множество $S$ с определённой на нём операцией $\odot: S \times S \to S$, $S_1 \subseteq S$, $S_2 \subseteq S$, тогда + \[S_1 \odot S_2 = \{ s_1 \odot s_2 \mid s_1 \in S_1, s_2 \in S_2\}.\] +\end{definition} + +\begin{definition}[TODO: ???] + Пусть дано множество $S$ с определённой на нём операцией $\odot: S \times S \to S$, $S_1 \subseteq S$, тогда + \[S_1^n = \{ \underbrace{s_1 \odot s_1 \odot \dots \odot s_1}_{\text{n раз}} \mid s_1 \in S_1\}.\] + При этом $S_1^0 = \{\varepsilon\}$% + \sidenote{В данном случае нулевая степень даёт единицу, как мы и привыкли.}. +\end{definition} +\marginnote{TODO: Я не понял, что со скобочкой стало} + +\begin{definition}[TODO: ???] + Пусть дано множество $S$ с определённой на нём операцией $\odot: S \times S \to S$, $S_1 \subseteq S$, тогда + \[S_1^* = \bigcup_{n = 0}^{\infty} S_1^n.\] +\end{definition} + +Многие прикладные задачи, в которых возникают языки, достаточно естественным образом формулируются в теоретико-множественных терминах. +Так, задача распознавания~--- это задача проверки принадлежности элемента множеству. +Далее мы рассмотрим прикладные задачи, решение которых требует, например, проверки включения одного языка в другой, или проверки непустоты пересечения двух языков. +Разрешимость таких задач, алгоритмы решения, их сложность и другие свойства, зависят от свойств языков. +Это даёт дополнительную связь теоретико-языковых конструкций с решением прикладных задач, позволяя более аккуратно рассуждать о свойствах получаемых решений. + +\section{Производные} + +Производные для языков предложил Януш Бжозовский в работе~\sidecite{10.1145/321239.321249}. + +\begin{definition}[Производная Бжозовского] + Производная $\partial_c L = \{ w' \mid w \in L, w = cw'\}$. +\end{definition} + +Заметим, что если для слова $w$, $|w| = n$ верно, что +\[\varepsilon \in (\partial_{w[n-1]} \circ \dots \circ \partial_{w[1]} \circ \partial_{w[0]}) (L),\] +то $w \in L$. +Таким образом, существует возможность использовать производные для проверки принадлежность слов заданному языку. +Данная возможность активно используется для регулярных языков~\sidecite{caron_champarnaud_mignot_2014}, языков, распознаваемых автоматами, управляемыми входом (Input Driven Pushdown Automata, IDPDA)~\sidecite{10.1145/3591472}, и контекстно-свободных языков~\sidecite{10.1145/2034773.2034801, 10.1145/3022671.2984026}. +Кроме этого, с помощью производных можно построить элегантный алгоритм построения конечного автомата по регулярному выражению~\sidecite{10.1017/S0956796808007090} и для выполнения регулярных запросов~\sidecite{10.1145/2949689.2949711}. + +\section{Распознаватели} + +Распознаватель может быть сконструирован как некоторая формальная машина, которая принимает или отвергает те или иные слова, записанные на входной ленте. +Таким образом, язык задаваемый некоторым вычислителем~--- это множество принимаемых им слов. +Далее становится возможно классифицировать языки по тому, какого класса распознаватель необходим и достаточен, чтобы их задать. +Например, можно выделить класс языков, задаваемых конечными автоматами. +На этом, в частности, построена \emph{иерархия Хомского}. + +\section{Генераторы} + +Один из базовых способов задать генератор языка опирается на \emph{системы переписывания строк}, из которых, в дальнейшем, можно получить так называемые \emph{порождающие грамматики}. + +\begin{definition}[Система переписывания] + \emph{Система переписывания (строк)}% + \sidenote{Один из классически примеров систем переписывания строк~--- это машины Маркова, или алгорифмы Маркова~\cite{markov1954theory}.}~--- + это пара $R = \langle \Sigma, P \rangle$, где $\Sigma$~--- алфавит, $P= \{p \mid p = w' \to w'', w' \in \Sigma^+, w'' \in \Sigma^*\}$~--- набор правил переписывания. +\end{definition} + +Один шаг работы системы состоит из замены любого вхождения любой из левых частей правил на соответствующую правую часть правила. +Иными словами, пусть есть слово $w = w_0 w_1 w_2$ и имеется правило $w_1 \to w_3 \in P$. +Тогда после переписывания по этому правилу будет получено слово $w' = w_0 w_3 w_2$. +Заметим, что выбор заменяемого вхождения, как и выбор применяемого правила недетерминирован: может быть выбрано любое из вхождений и применено любое из доступных правил. +В качестве критерия остановки выберем невозможность применить ни одно из доступных правил. +Получившееся при этом слово будем считать результатом работы машины. +Зафиксировав стартовую строку и набор правил, можно достаточно естественным образом получить язык, как множество всех слов, являющихся результатом работы машины. + +Представленная система является, скорее, неформальной базой для создания более содержательных систем. +Далее, накладывая дополнительные ограничения на правила машины и алгоритм её работы, мы будем получать некоторые содержательные классы языков. + +Отметим, что подход к определению языков через системы переписывания не всегда удобен. Например, не получается с их использованием естественным образом определить булевы языки. + +\section{Классы языков} + +Иерархия языков, предложенная Ноамом Хомским (Noam Chomsky), является на текущий момент классической и представлена на рисунке~\ref{fig:Chomsky}. +Она основана на сопоставлении языкам тех или иных формальных вычислителей, способных их распознать. +Например, для распознавания любого регулярного языка достаточно конечного автомата. Для контекстно-свободного~--- магазинного автомата. И так далее. + +\begin{figure} + \caption{Иерархия языков по Хомскому} + \label{fig:Chomsky} + \begin{center} + \includegraphics[width=0.9\textwidth]{figures/Chomsky.pdf} + \end{center} +\end{figure} + +Однако, данная иерархия постепенно теряет свою актуальность, так как появляются новые классы языков, свойства которых уже не удаётся адекватным образом отобразить, используя её. + +Один из вариантов иерархии языков, более полно отображающий современное состояние дел, предложен Александром Охотиным% +\sidenote{ + Иерархия и некоторые отражаемые ей свойства подробно обсуждаются в презентации Александра Охотина \enquote{Underlying principles and recurring ideas of formal grammars} (\url{https://users.math-cs.spbu.ru/~okhotin/talks/grammars_lata_talk.pdf}). + Также, с данной презентацией рекомендуется ознакомиться чтобы представить себе состояние области в целом. +}. +Вариация предложенной Александром Охотиным иерархии представлена на изображении~\ref{fig:hierarchyOkhotin}~ +\sidenote{Данная вариация скомпонована из версии, представленной в презентации \enquote{Underlying principles and recurring ideas of formal grammars} и версии, взятой из работы~\cite{MRYKHIN2023113829}.}. +Приведённая диаграмма содержит регулярные и контекстно-свободные. +Так и подклассы, лежащие между ними. +Вместе с этим, классы, лежащие выше контекстно-свободных: многокомпонентные контекстно-свободные, булевы, конъюнктивные, их подклассы. + +\begin{figure*}[h!] + \caption{Иерархия. \emph{Reg}~--- регулярные, \emph{LLLin}, \emph{LRLin}, \emph{UnambLin}, \emph{Lin}, \emph{LL}, \emph{LR}, \emph{Unamb}~--- однозначные, \emph{Ordinary}~--- обыкновенные (контекстно-свободные) + \emph{Conj}~--- конъюнктивные, \emph{Boolean}~--- булевы, \emph{UnamnbBool}, \emph{UnambConj}, \emph{VPDA}, \emph{LinConj}, \emph{UnambTAG}, \emph{TAG}, \emph{MCFL},} + \label{fig:hierarchyOkhotin} + \begin{center} + \begin{tikzpicture}[node distance=1.0cm,bend angle=45,auto] + \tikzstyle{lang}=[circle,thick,draw=blue!75,fill=blue!75,minimum size=1mm] + \node [lang] (reg) [label=below:\emph{Reg}] {}; + \node [right of = reg] (reg_dummy) {}; + \node [lang] (lllin) [right of=reg_dummy, label=below:\emph{LLLin}] {}; + \node [right of = lllin] (lllin_dummy) {}; + \node [lang] (lrlin) [right of=lllin_dummy, label=below:\emph{LRLin}] {}; + \node [right of = lrlin] (lrlin_dummy) {}; + \node [lang] (unamblin) [right of=lrlin_dummy, label=below:\emph{UnambLin}] {}; + \node [right of = unamblin] (unamblin_dummy) {}; + \node [lang] (lin) [right of=unamblin_dummy, label=below:\emph{Lin}] {}; + \node [right of = lin] (lin_dummy) {}; + \node [right of = lin_dummy] (lin_dummy_2) {}; + \node [right of = lin_dummy_2] (lin_dummy_3) {}; + \node [lang] (conj) [right of=lin_dummy_3, label=below:\emph{Conj}] {}; + \node [right of = conj] (conj_dummy) {}; + \node [lang] (bool) [right of=conj_dummy, label=right:\emph{Bool}] {}; + + \node [above of = lrlin] (lrlin_up_dummy) {}; + \node [lang] (ll) [above of=lrlin_up_dummy, label=above:\emph{LL}] {}; + \node [right of = ll] (ll_dummy) {}; + \node [lang] (lr) [right of=ll_dummy, label=above:\emph{LR}] {}; + \node [right of = lr] (lr_dummy) {}; + \node [lang] (unamb) [right of=lr_dummy, label=above:\emph{Unamb}] {}; + \node [right of = unamb] (unamb_dummy) {}; + \node [lang] (ordinary) [right of=unamb_dummy, label=right:\emph{Ordinary}] {}; + + \node [lang] (conjleftcontext) [above of=conj_dummy, label=right:\emph{Conj$+\lhd$}] {}; + + \node [below of = lrlin] (lrlin_down_dummy) {}; + \node [lang] (vpda) [below of=lrlin_down_dummy, label=below:\emph{VPDA}] {}; + \node [below of = lin] (lin_down_dummy_1) {}; + \node [below of = lin_down_dummy_1] (lin_down_dummy_2) {}; + \node [right of = lin_down_dummy_2] (lin_right_dummy_1) {}; + \node [lang] (linconj) [right of=lin_right_dummy_1, label=below:\emph{LinConj}] {}; + + \node [lang] (unambtag) [above of=unamb_dummy, label=above:\emph{UnambTAG}] {}; + \node [right of = unambtag] (unambtag_dummy) {}; + \node [lang] (tag) [right of=unambtag_dummy, label=above:\emph{TAG}] {}; + \node [right of = tag] (tag_dummy) {}; + \node [lang] (mcfl) [right of=tag_dummy, label=above:\emph{MCFL}] {}; + + \node [above of = linconj] (linconj_above_dummy) {}; + \node [lang] (unambconj) [right of=linconj_above_dummy, label=below:\emph{UnambConj}] {}; + \node [right of = unambconj] (unambconj_dummy) {}; + \node [lang] (unambbool) [right of=unambconj_dummy, label=right:\emph{UnambBool}] {}; + + \node [below of = linconj] (linconj_below_dummy) {}; + \node [lang] (rtca) [right of=linconj_below_dummy, label=below:\emph{RT-CA}] {}; + \node [right of = rtca] (rtca_dummy) {}; + \node [lang] (ltca) [right of=rtca_dummy, label=right:\emph{LT-CA}] {}; + + \path[->] + (reg) edge node {} (lllin) + (lllin) edge node {} (lrlin) + (lrlin) edge node {} (unamblin) + (unamblin) edge node {} (lin) + + (lllin) edge node {} (ll) + (ll) edge node {} (lr) + (ll) edge node {} (lr) + (lr) edge node {} (unamb) + (unamb) edge node {} (ordinary) + + (lrlin) edge node {} (lr) + (unamblin) edge node {} (unamb) + (lin) edge node {} (ordinary) + + (reg) edge node {} (vpda) + (vpda) edge node {} (lr) + (vpda) edge node {} (linconj) + + (ordinary) edge node {} (conj) + (conj) edge node {} (bool) + (conj) edge node {} (conjleftcontext) + + (unamb) edge node {} (unambtag) + (ordinary) edge node {} (tag) + (unambtag) edge node {} (tag) + (tag) edge node {} (mcfl) + + (lin) edge node {} (linconj) + (linconj) edge node {} (unambconj) + (unambconj) edge node {} (unambbool) + (unambconj) edge node {} (conj) + (unambbool) edge node {} (bool) + (unamb) edge node {} (unambconj) + + (linconj) edge node {} (rtca) + (rtca) edge node {} (ltca) + ; + \end{tikzpicture} + \end{center} +\end{figure*} + +Для того, чтобы содержательно рассуждать про различные классы языков, необходимо иметь механизм, позволяющий чётко отделить один класс от другого. +\emph{Лемма о накачке} для соответствующего класса~--- один из классических таких механизмов. +Однако, не для всех классов языков соответствующие результаты получены. +Так, например, формулировка леммы о накачки для многокомпонентных контекстно-свободных языков в общем виде всё ещё не найдена, хотя существуют формулировки для отдельных подклассов. +Аналогично, для булевых и конъюнктивных языков всё ещё не предложены аналоги лемм о накачке. + + +%\section{Вопросы и задачи} +%\begin{enumerate} +% \item !!! +% \item !!! +%\end{enumerate} diff --git a/tex/figures/Chomsky.pdf b/tex/figures/Chomsky.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a0d4d3b70996b90dfdd1823f81da8ab0f23c9192 GIT binary patch literal 14109 zcmdse1yoes+pmG5Lr8ZF9g0jaz#t*r-5@A2beA+rcS|EE0@BhFiqc36NXG!u5(Wt$?yKcd-B?0FfF93@PD)^Z;R(^Jh=m2QX?6#mE8C_(m+_pPJ9^IP+&qiDdk^~@!TrQ<`z`Xai}BBMTI{}? z9BSHNMZdDl%ntcB8~H9Rk+I=sYPJ=<1wXfI-z$yFJwbPtIMkXdee^O14Id?{wHpk1 z%EneG6PJ@b?z~`LjC#S`?tEarA9ws<{vUTpF!JQ?M@cDrJ4~^k?U->vxS(Jt1e4`= z83YW4{*(bFfqy^71_Pv+F=BeJ;o*P+bE_Dcqrfa+D5f|NaY6wN{3^?>h%&V_60>&) z>jMQLU<4oRI)D@pFBA;tfdaR1Brg(da8gzr=o(Pi8H_RDQ)`uWvUhd(t-Gf!o=AW8 zRvqYvlaZaX1EysYkDp>$u#1x`>Ss(G$R&Ytvot}eNsD2GKhRJ^IorEBnV_7(7@ev8 zHckwrKgaoF5kxG3{33JWD!B5cZbIbCB)8s5i>M2 zBWg6RZC_)4KGo&i^O~h4Cz=;w@4_#pw!rQ9M8Xe>VZ8C2lwy0anC_+BH)w$uY5OjW2WT@(3==c9PF9)g`ptaI-E} z!cWF#QPM?73LaVweUb`cqPdYF%g<`#7~(B4J7E^i@+`DjesP1-3^yJ`P8vv6cky6` z=XG+=+mfVmQ4Qo1IVm}ms>m?!_0PTco-PnXbTKeE^|WMNv~at3wxOTKSH$A^@fWL@ zFjmjAjo5;^|6&2Zt-nxS*e?tC>k0TjvjEH*`lkh)tgt85{=dEmoIExD_VBk=?gpKM z;sOu=v@Soy=c*1mX+Ib?=jOAStC>q)MKJgJsOATlM*dUJEw(cq)GG1C3rcVQLBZ=Z(g&g1Q#(>fHy z{TCDXIZOXo1pZpT|7RwEd3gS50w)jD|1V773Ug=Hz(HvIH*Q$cU(^a6$S;Gd} z(v<6#6gGU3m-Jw9>~Tk+FB2L6#a8xP>V#sY7bxSSe0tYz&7tlfa_leb%S_u3EOa+> zIBI>c;?v{d(h+_^z5kkQ|L#Zs^{m+q%tN3%N1*v%^#4;qC;Er{S_1x>y8ko%!!U0x ze;5Gluh*OZv<95MGC;vR5Ptr@;rl_$%Uz?5RK(fuuG^=H-sxUef(lvQ!1oMT&A|lc zL#+cr5*+cNVHC_25>M35i5f!vCH(JE5a^PeFC|hvU#%ZOAjt({1X*elH5KYecv$G} z46?humhCSc^R3SMR{LS!)y#Y|!`ZBFfp7U?19K>QbP`b~!d45l=ardGPQ2cnB(mHedwJs$&l zs09Kjlcak-F(zCPJhCB$Fk}U-ACT8iV6r{YK3MHnSc30F@ z+URNu7(5l72ugTkU*mf?a!Xx=h(zPIWi{&!-KVe8Ej(j+^|;LZrzK<^wH7QKAq7<% z$nf9jw<3?La)B4@?#@qu|)JY@UR}T0DpADLd zL2g}q#>t($U6;ntzOHV!No;<@gR?XjA_suuRj zT%B1g`KFd3izQuHS=;T<97k!rW`2tuKQECCn>IILJZ3CZ`4HLD7h9q~oIDWLN6fG= ztjjcE`?>iRI%*H4VWw5@tt+4ziW|2vQ0e)3Ga-xNqoDYwklju0k4?8t_jyu3NyD_2 z-BKLB)R(L&?sX-OnkCU??7g+_7dqZ8#nZ15*7^8$Ds8k|IV|vSu5YU8b3obDrcZ#- zaeD)wjlPP3`ef0*Qu2C<`Q}*Ps%UTI`UZPx>WqXlmUd;fd&5H#@yPYiKEJu-#AIV- zH;bi>N1u-v^x)#PujzFRZ`)Ud42PP~7aEx>g=;Hkk(H@Plqu5;C0XowFV`3hKUwv6 zSy(}@XfCs&Sj@jvRc$F*?e)gJ@a=1HjI2(maX)1WkFu@)EKUK&X7yGf<`WK!H~AC?zjsnR*rmAy=soS2IDB~{m#)n6%K zE4wj&+p~0ttxI;P?W-|T#8$FUmrY1>>ruY!vS6Bh{R?Tu3BhHUm5jkV6Ws~ea>A}@ zT8TgB)Q0=93MU1JuQ#a~aoB^2Zt~JnLhFy5Wgd^wc}zIuwaGq=G&yYfg?&j$Nf(T# zpXpL}T;C=)@Nj>&oS<#z-6&v?8D{L7vCt&yCZYB&{Z`<;(hG|QW}wz~)3l6i1w#9( z+dWo}Wy>EY-(t}&sB{;IO?s2{ue8YpT zp?Bb`d#9O-TYqP9iQPnFs$V)^7J2#F)R#|d8KDn|HPQuoaugRG=@~zsE0jV!B@KT> z7}0869{gA}fKl_>eHU9n5qRgF=m$wE$?Sv=j2}H$pDLprh_3f+a58AQb)&-5%~f&@ z=R&Il^uc>q^7pdWxQ`l+^3(57OSiEOGS@gCQS~NCtVif74DTBm#ehm)Ost-`eBPB3|3Ff3Q@OdjCr{Rt*XO%JQQmNSvMPZ8glS3e9~qqsrLFysjuAe;(Cy5GJwTDixz2OT~T zI+r3BRqUm{7+D~9ZGMdD1@B`6{cL4YuH6FR5pVdqFM^10a;iXaF|=^y0v(RR#SWfZ z*E-}r^Drvr^M2y@A;>bvTM~#)v*7(`$y#Q$YUvs5G?y>+jwEVS1Kfm8Q2go`U8h<+ z`0^2NaamuMV!mtCdo+5i@w1EpxM&^z*7L;WQIore$LbJ9<`Ar1aK3>LbJ zRv*^VRN6!FI@(AB(25x%y3n3khx>9cd*zDF^P>1AF|iUmHs$K9hk`iILi zbq>|lf}hzXIR~z2hMRx7_CU#0b9v_SZELRY$!nzDlzO=(OSoN6vNxm@k8Iuvv(lG+ z6O8_(QXvE=0;+KvQ+y-r(f&S&pL@}erc~s(?wc$Ra&Wqbmh_cGlg7x zZkgJbZftAwz1*A2pr6&*sTRv`zCCsDCY<}*L332UwgH2PHvf8uxo==IKXH2&sW5G@ za=3#YIuV;qIk7XrH)Ae}O>TQfI$*KG$eZU<2dS_I|I+I$nuAv{IiRh{9Yflg=>QSV z#+J$10&(d>&59iS58CL?Nz0F+&6Aey@@T~%5%wd)N4+sEA+SZGAaP3fmVi-G{A;yc z=am}M{J((?Neorpb&blJw@3`t+*Q#Rf`mZ*liRlf^o8>W>b+uYG{;^PiEYjVOv~>X z^w+;H1=*9kdF+`_j}>g|i#$|4h!RslkAjpBx36Axv$@+%D{Nz5-u=O@YHWw(#y1TL zWlq6I&lJ&)H_}LJgv}o43%U1%OZ!~fPP#`Q!)`O40j_1YQMx(QQc%$q62eFM5v^eZ z+g72W(->Q+?TiBX;_z-i!t)h;Hp5B360xT>Mc-au?X@TnR2@a?^ntF}ppb87IVpX{2$r zN9!QB*;e-;s98ZjE<@K}pVVv^O~zVCl6UohB#&dNSOtlz-jWi34;0h|;$u%tZtMC8 zc{A_eBUjis6Cev3Eq}iru96l>WYihInX>Y#dLe$X8bmz5;~cazO5xPljJQ~;#cn2B z-u%2gm?k-}e3cCO?iB@2soFs*ea<(ET!-8wrZU_diz}t;v$K$Pf$)Qv zFWj(yc6E$jOP?@Ofcfhk&1cL{WFo}QZ7Io!Hi~83*9oGSAgZ4X|9pi$d7Z_);sUSGFkU3|=Q}j) zcdqXT2L}7EIk4a91cTUKyB08R$ChAF%!fyevfKqEl4anJAgAi&m_))3p8aXV&iF_f^XoO5oi229AB5ruL+|EBX``y&@Qnv!kjc^P5y zYpafW`~xE!GpZeir~69NUJA92JfZT)w=!LYv=Xh}Q3MPg}Z z4(8Ujv=g;+w)`nLX;|CR)WyOX;I`pV3=i@99~=n*W5VelocHv~3kTTx-@*y=4QSn7 z)6Np(ivgcZy5G@&{p7fQbLYTLsT;tI{v#9p^8=KZ4^Y?d({e<|%Uh%EMHaFNZr(q> zj7*;nj9oU<6}uE08%v&zWW@3a6+Oo)1Gy6!s^g!1kB~SV%|apv20d1MP>7Q#6=6#L zc!X*(b&czOlD=M1p!^Fw87^VFF@>);*ureLzD*r=d|US2v|HNf$w-|&nrYe!R1pgm zTf0QC_nJ+cIYF8TbV;?AK+HpPuO)_y`qQGZ*c3l2Hl1Nb{aOw!$3l5iGQnt+}Zomk135*=65oQ|-CO#YcV)71c+OJ9gf_i*H~Z%@uofd zZVMh+>28Y0n@1z=FU3HvTUeAN1)6ti7$vLjDO{`2FqOP0P+#Tm?~4xt;eJ@r8X%EO zLa1U5$F!*sR7ia5q$Jg@-F0!RzT{|pLC?g%G)jlCAgKB~b6F7cY9U2c6^N))j*t)~ zA7?{{dKkc)?Zap_KOuY;uSKfDu}BvCTSAHXvZ_6*UeQcLqM?;|P(xdqy24sdODhF@ z?n|ns*nU^|s)^9VW7&#!5>?~uF#mQ_Nx~g#)s7hQvVx5?Nv$&Io*t!D+EA>^(M?sAO3W@^XdCoyp7i#oygH!ta%l95;`f7wjPrIow-;@`&330o zIjP}zYDC=m5}7>E-8A1FQyWSubQ`4PtK6@^u*__~l0aCR279b+6bwCRn2zMe6XF!V z%RfEH(L<|DGH$R4uiFr?UZk0p@_%Q_veIs$)b~oKojH*AGwS_PB;{JZp4)Aj9h?zD>AE(?qAP8l99L6=l(l9KqEDwP^@^W?73Bk58vzd}L%WxY%+~ z^urglc(a-sT7i~ z^{~waLmlUU`Y(Ibe(2l!%)Fm{1)|?5zc-7a8~@g`ORSo-l{M+H{i-xL0K1LKH~#L9 z^$}L@lO1iXJcJOX9nsU87I6fsmAK)P_T~%Ewc!zwOu?NxhK`&gko-+r`IMISmFuEz z&jSK(4T2|g{0E_HEVxt(=5afDNemYDBaKQ#w2^OC-nj4*ER8@PI5au9O zh?x|>?_FsnZ@_l7X1lvSNL);I)-;kyvf@U>wF-+i73b{yTWj5Nwg$R-ehzgP6l*xM zbxk9(jr^ab14uvp{G%>b+L$WAsl?0iZb6?Yye$R75|iREnZW%=DA{eI^q%WLQyIY&M`-Cv{|y> zn-{tEplFpXuU;_)UtQJ-p$nO0T$^EGeZ1GM+})YmEcAE;MMhZYg&r^6M>0_LH+dRQ z@qgVb$$ObLe)|xbmjki8IB38*o?Gl%q(#|H9N|i0#cW6@B!wkeufmWMWfe16Jb7z| z+5XY~*{%M@$fWNk3K15wF2h*1bNc%m<8MB#cIhX6oY6nx>0bF_(Gk3N!?59~Vb<^6 zr;86~V-TU(Q3s$?N|z>k(Xca=G)N`-xwti7Bt2^T3&X=EUm^ftFyZR;(6 zt~aIAhrLwclx0^nzY4-Ht7j@Y7}{MpUVQ0tW?IB^ znzU)rNc#L1tI7#PdauB1BXtd96Y4qI{1Q!9fekImbBqlV$#`eqR+(9MRhiW-9>0ZX zVGA|c=vC&ouI#@|zWwf<*@WbW*6mSH)w$Z$YBHwPA}7D~tx9XCE{a2=iGh$+9>o8+ z1d2a`zPreur?XYw=g_0Mq(`pL$G=8{hhO^uOw4Omi?l7JSR>U?MM1SB-4E4$*}#lOp9?ZF(fbSc%CwYzp{!s)}8=yT@xuc|i$tZ0zC z3`l0K#@h|Pzx;-I-L!*bnIyUNL2Rl^9)vo)&6rm@%{G;3Hh;=I(>C3f+c~K&yqZ&w zO90 zq6pc-3!lihsRe0pbyd;azbCTxO~vBj{hHW&4C{CIgu=00((e*EHl*MYrstQ{P!ky7 zP9$oX4W}#RFs3khBNbAHONcQi+g+|A}e4Ad@6EKm% zie&o_pFO&#Y~&$=WkGQhbXx^anDXgoucnp@7g9t7d1i|*d`pRFWt56xT3?kKteYtx zq59ma$BsOF^H|p7O4ChgHOtRejr(5j?sk9pkUTWBe}&RtvqyH?rFeF? z@>ox$6; zS1X_9;8r|Y>Uh3`HT9Z&-rN}(MVc{zXO?%wC5p1nMTVlXa3cl5Z_j zYaCyBS0A-xc}yeDCEj~=Mg)BYJ*|viYEXZJ21Ht8C+MEHOh#(x_i|pQOMI*E+d3XY zL!lY^V?@YM-hT1)?drL2+A|*g28UBmRS(tGna=M&a9r|11#ZUOy(~i7rB`Hn-#zL3 zeuRAM^H{3nVj1lv{Wg3nsl~hQcx7NeexG`_w&z|Oq?`>yLBv8A0+(V5kO8y%UA`5` zFN1S9tNLIWmP9j*dyAJdzTA8GC_ONaf1j#Ov=99TZxMHc{BovTg=11|gaVk)@-i}# z2Q=^rbd6{}hH~C$#}LYFNIEG?H#0QZ269C925XPee5R^7$AA5~Y7H~dJku``hSMC&QxW?L$8apuPBEj901rQ3PSu?;yc zv`A&cGpf%c8Ws9;ZkczEn$jj-s&+?rk`=~&CzdIq-QQy9CXCC-*J=)O$+%&26ccof zC+jjKK9jGBPloH^EwRtC3|%HW3mn1ihB@>D*9-3R#5qH*B)#6Uc(Fo0OR&W_`IYAk zsVVi_8Iz5;LP(BQ$}Ckt{WG=V?8B~Q;~*5nTVXqyKyx~>P06rAnX5Gq;=^H4IeX78 zBM~#Kv2NWO(DVCD7rLnu(_(XD#mP*{f@v7-X zzr`osxvtJ)C~d$b2vae}nc&)dZW)XO-g;~|J{H8WqryjjQE zqKdt}V*y3Sn>1Z-IM$*Wbng3Zlh>EkPQsyZ`Gj;YR>h5cfdXU3zFy9@QfRYfMi$SY zw>iy3&$$D>+{ef-uO++EM|zLT(?>$uqj~1fX!40@cnX@YoiE+F9mhQ0`E_xsjdB+E z$k&+xHm#d?tND?_SGN@9ZWF=#1Z>}z#P$`;b-y3Yik#gY;M}1>vbe>e<|&*sY*=c` zv0w&ADaCi_oD!p$q;pgG{pxDdQTtKj47dC)jAD1W?+CsuYWBrB_7yE0m-_hB9lLRxBr8CFdRuagpVZSYocc?MY=k&26DMi0=` z3vJV%J>bQ8X&G3SxlJ09PIF9kk2`ZaS?W3AJ#OCF*DvQBUJ#Zd#I*U2>Zp%1Tb51G z%EWV=A%5NdS2HWe9!RaU24z;xeKe=saN_e$I-BKmz!aifF?WUTz=!G9{PqpLqjjq1 z?zq0)=yTVbo?Yy_t6;V~db7ine}A3dExM&_VeU4+cMqBgziED8=8}0ob44XhA9M5S zHU2hqi)WM%#g&enM^P=*lRidXS2Qd zSa+JJ{X1QrQP0e63xtgFAGP8g@;81BPk51bp^P8h@n9fOK8*@3O=IZW)n~Z09Z&oD zB}MmVt>y?XjnBr{HdKvjNe$<=y>kMD`X3FRZEzSWl^PqLGrbWa8bIvk(sHGi-b7^a znU6kl(igX8G;GqB;LhY5qx9>?;4}J28xK2@$!2t&>NCo=DQ|3>2@8{Sz;At#+QC?y zrC3_Ak#80SE1sa>inRS0he2VTz_r!f4hP=Nk zZdm%}qhM^hiAf#j;@BMpM$;Q$>#8V}BZX~14=#1L%gtassVI#xc2X%$2qVth5NsV! z7F=cLO7vM7=ay%~XQj>$9J5DxSwmC2Pd^;%Y}+6wmF2hD-M>=y`Mu9w7rhPnWEuI)J#9KM&+RCpAgVO z*GogQ@qB^~j~8Eylms7kJprjB2-fru<(Aw%!##J+q4+u{vD7)u`wrO*db&*y^1k~W z#D2HFc-*1fJbUJ01M1Gdkj6iEG68HK0s`at#Tx(I`1Ct3c)FkGKkFNr!x3LpKGj_9+WY8s2mI=e;wd;-BV=2CJh2d|naQ8*%Tkb!} zkESPLl$*^k<4d{v;pKHM;c7l>KX=ngm84;W<)%*qx#jKmor%HoJ~=OhudUA{e?tmu zcPC<#9k3uQAC_orJgIY1L-~$q?D>vdrv9efe}#SBbC1j58IFDb8^NOU@9&47e|m;A z8>T|JdZy&Okl4DYw91Buzj{F5fN^H)Ch}>(CoHw>F?DPrqSgV5;T*R5P+Y2vb6@1n zhJSesUy7jmNXo*#bi+Tk>?Y%V@1S!GSvQ3VKhd`AbU4pkET2w0OdRP&ip)7wH=EX` z;s@@NGhlPMPWa;9sz2A!+-5ag8kg6^w-Ymzq8IKgfd2S%JNI7iYrPg z{%^4SJijXXzlr2O-8c(a;Lkns7(V>JBl*Q;B`|Ys=!e2!HzrzC*Q1@^K{0y>o zX7(5yFkq{p%q@XUu7F=e6xg1RI`N2LriikWDar{$?X%080*(wz7mr^_>aGqBHYi(+ zd*j4+0rdN1QURU$%Pj*wQK{NViZ)mu0=NNqArK(I!Msoe7y&T%2qYAs`;mYQbL9c^ zBH&;?ejpC)xaZ{ou9!Fk6NiEk{4gLN4;TT+5hr;7R{>BS0SC$go0|C$JU{^AfK$Q1 z0K@73fbwMb{(lE02E$V~%zuaBPX`B>`zI`1GACm^b@-SX0gf90hZC;{Mu}>tyZ3){ zVVrJ}{jG!lP&MYvz^U6x-qI9P)5(VPU*`Z^F-Hh~8zF$eU&f;1WN+$f0-RxCH!-qw zvIj%2LwT=5!0Z+-E)LED+`w51Kx*z}fYU_mKKDJckq z2MK}jN&-O)0^x%LS4@Bc_YmNUfB=3m2m}tqVL%=@5czcl394-oixegr^-!j`WCVDIoledesatxYFm{Sr ue%0*lT>uX*X3aT?V-|V9^Li2oY}?tz$jRlzvY~J|a2kMxMN(M`^uGYERL + + + + + + + + + + + Регулярные (Тип 3) + Контекстно-свободные (Тип 2) + Контекстно-зависимые (Тип 1) + Неограниченные (Тип 0) + + diff --git a/tex/main.tex b/tex/main.tex index fc04112..27d6929 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -17,7 +17,9 @@ \usepackage[]{pseudo} \newtcbtheorem{algorithm}{Листинг}{pseudo/booktabs, float, floatplacement=h, separator sign={.}}{algo} - +\pghyphenation[]{russian}{% +тео-ре-ти-ко-мно-жест-вен-ных +} \tikzexternalize @@ -45,6 +47,7 @@ \input{LinearAlgebra} \input{GraphTheoryIntro} +\input{FormalLanguageTheoryIntro} \backmatter \setchapterstyle{plain} From ac29ebea8bd2148bbe890dea0b967814d469f067 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Tue, 18 Jun 2024 12:29:34 +0300 Subject: [PATCH 20/29] Add Regular Languages chapter --- tex/RegularLanguages.tex | 275 +++++++++++++++++++++++++++++++++++++++ tex/main.tex | 1 + tex/styles/theorems.tex | 12 +- tex/styles/tikz.tex | 14 +- 4 files changed, 296 insertions(+), 6 deletions(-) create mode 100644 tex/RegularLanguages.tex diff --git a/tex/RegularLanguages.tex b/tex/RegularLanguages.tex new file mode 100644 index 0000000..de98dd7 --- /dev/null +++ b/tex/RegularLanguages.tex @@ -0,0 +1,275 @@ +\setchapterpreamble[u]{\margintoc} +\chapter{Регулярные языки} + +В данном разделе мы обсудим регулярные языки~--- класс, лежащий на самом нижнем уровне иерархии Хомского. +Будут рассмотрены основные способы задания таких языков: \emph{регулярные выражения}, \emph{конечные автоматы}, \emph{лево(право)линейные грамматики}. +Обсудим основные свойства регулярных языков, такие как замкнутость относительно различных операций, а также различные свойства соответствующих автоматов и грамматик. + +\section{Регулярные выражения} + +Регулярные выражения~--- один из классических способов задать регулярный язык% +\sidenote{ + Замечание для программистов. + Важно понимать, что речь идёт о формальной конструкции, а не о том, что называется регулярными выражениями в различных языках программирования или библиотеках, где под названием \enquote{регулярные выражения} могут скрываться конструкции, существенно более выразительные, чем обсуждаемые здесь. +}. +Основывается этот способ на предложении синтаксиса для описания \emph{регулярных множеств}% +\sidenote{Помним, что язык~--- это множество слов.}. + +\begin{definition}[Регулярное множество] + Регулярное множество (над алфавитом $\Sigma$) это: + \begin{itemize} + \item $\varnothing$; + \item $\{\varepsilon\}$; + \item $\{t\}$, $t \in \Sigma$; + \item $R_1 \cup R_2$, где $R_1$ и $R_2$~--- регулярные множества; + \item $R_1 \cdot R_2$, где $R_1$ и $R_2$~--- регулярные множества; + \item $R^*$, где $R$~--- регулярное множество. + \end{itemize} +\end{definition} + +Для того, чтобы описывать такие множества, удобно пользоваться \emph{регулярными выражениями}. + +\begin{definition}[Регулярное выражение] + Регулярное выражение (над алфавитом $\Sigma$) это: + \begin{itemize} + \item $\varnothing$; + \item $\varepsilon$; + \item $t$, $t \in \Sigma$; + \item $R_1 \mid R_2$, где $R_1$ и $R_2$~--- регулярные выражения; + \item $R_1 \cdot R_2$, где $R_1$ и $R_2$~--- регулярные выражения; + \item $R^*$, где $R$~--- регулярное выражение; + \item $(R)$, где $R$~--- регулярное выражение. + \end{itemize} +\end{definition} + +Отметим несколько важных с прикладной точки зрения моментов. +Во-первых, часто используется расширенный синтаксис, в который добавляются конструкции не увеличивающие выразительную силу, но упрощающие запись. +Например, встречаются следующие расширения% +\sidenote{ + Существуют и другие, однако их мы не будем использовать и, соответственно, рассматривать. + Читатель может вспомнить, что называется регулярными выражениями в его любимом языке программирования и попробовать самостоятельно выразить имеющиеся там конструкции через базовые.}. +\begin{itemize} + \item $R? = R \mid \varepsilon$, где $R$~--- регулярное выражение. + \item $R^+ = R \cdot R^*$, где $R$~--- регулярное выражение. +\end{itemize} + +Во-вторых, конструкции $\varnothing$ и $\varepsilon$ используются крайне редко, особенно в случае расширенного синтаксиса, так как часто выражение, эквивалентное использующему данные конструкции, часто более компактно записывается с использованием расширенного синтаксиса. +В-третьих, оператор конкатенации часто опускается% +\sidenote{Как и знак умножения во многих математических записях.}. + +Рассмотрим несколько примеров регулярных выражений. +\begin{example} + Регулярное выражение $a$ задаёт регулярное множество $\{a\}$ и, соответственно, язык из единственного слова $a$. +\end{example} + +\begin{example} + Регулярное выражение $ab$ задаёт регулярное множество $\{ab\}$ и, соответственно, язык из единственного слова $ab$. +\end{example} + + +\begin{example} + Регулярное выражение $a^*$ задаёт регулярное множество $$R = \bigcup_{i=0}^{\infty}{a^i} = \{\varepsilon, a, aa, aaa, \ldots \}$$ и, соответственно, бесконечный язык, содержащий для любого неотрицательного целого $n$ цепочку из символов $a$ длины $n$. +\end{example} + + +\begin{example} + $a^*b$ +\end{example} + +\begin{example} + $(a\mid b)^*$ +\end{example} + +\begin{example} + $(ab)^*c?$ +\end{example} + +\section{Конечные автоматы} + +\emph{Конечный автомат}~--- вычислительная машина, которая имеет конечный набор состояний и может совершать переходы между ними, читая входные данные. +Важно отметить, что ни какой дополнительной памяти классический конечный автомат не имеет% +\sidenote{Существуют автоматы с константной памятью, регистрами} и не производит дополнительных действий% +\sidenote{Автоматы с записью на ленту, и т.д.}. + +\begin{definition}[Недетерминированный конечный автомат] + \label{def:NondeterminicticFiniteAutomata} + \emph{Недетерминированный конечный автомат} (НКА)~--- это пятёрка $M = \langle Q, Q_S, Q_F, \delta, \Sigma \rangle$, где + \begin{itemize} + \item $Q$~--- конечное множество состояний; + \item $Q_S \subseteq= Q$~--- множество стартовых состояний; + \item $Q_F \subseteq Q$~--- множество финальных состояний; + \item $\delta \subseteq Q \times (\Sigma \cup \varepsilon) \times 2^Q$~--- функция переходов, а $\varepsilon \notin \Sigma$; + \item $\Sigma$~--- конечный алфавит. + \end{itemize} +\end{definition} + +Так как нас интересуют конечные автоматы в контексте языков, то будем говорить, что на ленте автомата записано какое-то слово (или строка). +Иными словами, будем говорить, что автомат принимает на вход слово или строку. + +Процесс вычислений, проделываемых конечным автоматом, удобно описывать в терминах переходов между \emph{конфигурациями}. + +\begin{definition}[Конфигурация] + Конфигурация $c$ конечного автомата $M = \langle Q, Q_S, Q_F, \delta, \Sigma \rangle$~--- это пара $(q, w)$, где $q\in Q$~--- это текущее состояние автомата, а $w \in \Sigma^*$~--- непросмотренная часть входной строки. +\end{definition} + +\begin{definition}[Переход в НКА] + Будем говорить, что автомат $M = \langle Q, Q_S, Q_F, \delta, \Sigma \rangle$ может перейти из конфигурации $c_1 = (q_1, w_1)$ в конфигурацию $c_2 = (q_2, w_2)$, если + \[c_2 \in \{(q_2,w_2) \mid w_1 = aw_2, (q_1,a, q_2) \in \delta\} \cup \{(q_2,w_1) \mid (q_1, \varepsilon, q_2) \in \delta\}.\] + Обозначать этот факт будем как $c_1 \to c_2$. +\end{definition} + +\marginnote{TODO: Без идей что тут написано, но жирная стрелочка для перехода выглядит естественнее} +$$С_2 = \{(q_2,w_2) \mid w_1 = aw_2, (q_1,a, q_2) \in \delta\} \cup \{(q_2,w_1) \mid (q_1, \varepsilon, q_2) \in \delta\}.$$ +$$ c_1 \Rightarrow C_2 $$ + + +Стартовая конфигурация. + +Финальная конфигурация. + +Ошибочная конфигурация. + +\begin{example} + Пример интерпретации конечного автомата. +\end{example} + +\begin{definition}[Детерминированный конечный автомат] + \label{def:DeterminicticFiniteAutomata} + \emph{Детерминированный конечный автомат} (ДКА, Deterministic Finite Automata, DFA)~--- это пятёрка $M = \langle Q, q_S, Q_F, \delta, \Sigma \rangle$, где + \begin{itemize} + \item $Q$~--- конечное множество состояний; + \item $q_S \in Q$~--- стартовое состояние; + \item $Q_F \subseteq Q$~--- множество финальных состояний; + \item $\delta \subseteq Q \times \Sigma \times Q$~--- функция переходов; + \item $\Sigma$~--- конечный алфавит. + \end{itemize} +\end{definition} + +Заметим, что функцию переходов можно представить разными способами в зависимости от того, как именно представлена функция переходов: список троек, матрица, граф. + +\begin{example} + Пример КА. + % \begin{tikzpicture} + + % \end{tikzpicture} +\end{example} + +\begin{example} + Пример интерпретации конечного автомата. +\end{example} + +Построение КА по регулярному выражению и регулярному выражению по КА. На производных. + +Построение регулярного выражения по КА. + +Алгоритмы: проверка пустоты ... + +Примеры. + + +\section{Лево(право)линейные грамматики} + +Наложив некоторые ограничения на внешний вид правил грамматики можно получить грамматики, задающие регулярные языки. + +\begin{definition}[Леволинейная грамматика] + Грамматика $G=\langle \Sigma, N, P, S \rangle$ называется леволиненйной, если все её правила имеют вид + \[N_i \to \alpha w,\] + где $N_i \in N$, $\alpha \in \{\varepsilon\} \cup N$, $w \in \Sigma ^*$. +\end{definition} + +\begin{definition}[Праволинейная грамматика] + Грамматика $G=\langle \Sigma, N, P, S \rangle$ называется праволиненйной, если все её правила имеют вид + \[N_i \to w \alpha,\] + где $N_i \in N$, $\alpha \in \{\varepsilon\} \cup N$, $w \in \Sigma ^*$. +\end{definition} + +Ноам Хомский и Джордж Миллер в работе~\sidecite{chomsky1958finite} показали, что лево(право)линейные грамматики задают регулярные языки. +Приведём процедуры построения автомата по грамматике и наоборот, грамматики по автомату. + +Пусть дан конечный автомат $M = \langle \Sigma, Q, q_s, Q_f, \delta \rangle$. По нему можно построить праволинейную грамматику $G=\langle \Sigma, N, S, P \rangle$, где +\begin{itemize} + \item $N = Q$ + \item $P = \{ q_i \to t q_j \mid (q_i, t, q_j)\in \delta\} \cup \{ q_i \to \varepsilon \mid q_i \in Q_F\}$ + \item $S = q_s$ +\end{itemize} + +Аналогичным образом строится автомат по праволинейной грамматике. +Упростить процедуру можно если заранее привести правила к виду $N_i \to tN_j$, где $t\in \Sigma$, добавив необходимое количество новых нетерминалов: +правило вида $N_i \to twN_k$ преобразуется в два правила +\begin{align*} + N_i & \to tN_l \\ + N_l & \to wN_k, +\end{align*} +после чего аналогично преобразуется правило для $N_l$. + +Пример построения грамматики по автомату. + +Автомат по грамматике. + +\section{Лемма о накачке} + +Лемма о накачке для регулярных языков позволяет проверить, что заданный язык не является регулярным. + +\begin{lemma} + Пусть $L$~--- регулярный язык над алфавитом $\Sigma$, тогда существует такое $n$, что для любого слова $\omega \in L$, $|\omega| \geq n$ найдутся слова $x,y,z\in \Sigma^*$, для которых верно: $xyz = \omega, y\neq \varepsilon,|xy|\leq n$ и для любого $k \geq 0$ $xy^kz \in L$. +\end{lemma} + +\begin{proofSketch} + \begin{enumerate} + \item Так как язык регулярный, то для него можно построить конечный автомат $M = \langle Q, q_s,Q_f, \delta, \Sigma \rangle$. + В том числе, минимальный по количеству состояний. + \item В качестве $n$ возьмём $|Q| + 1$. + \item Легко заметить, что для любой цепочки $w \in L, |w| > n$ путь в автомате, соответствующий принятию данной цепочки, будет содержать хотя бы один цикл. + Действительно, в ориентированном графе с $k$ вершинами (а именно таким является автомат по построению) максимальная длина пути без повторных посещений вершин (соответственно, без циклов) не больше $k - 1$. + \item Выберем любой цикл. Он будет задавать искомые цепочки $x, y$ и $z$ так, как представлено на рисунке~\ref{fig:reg_lang_pumping_lemma}. + Заметим, что вход в цикл и выход из него в общем случае могут не совпадать, что даёт несколько вариантов разбиения пути на части, и на рисунке представлен лишь один из возможных. + \qedhere + \end{enumerate} +\end{proofSketch} + +\begin{figure} + \caption{Иллюстрация идеи доказательства леммы о накачке для регулярных языков: любой путь в графе, длина которого достаточно большая, может быть разбит на три части из леммы ($x$~--- красный подпуть, $y$~--- синий, $z$~--- зелёный), а многократный проход по циклу $y$ позволяет \enquote{накачать} слово.} + \label{fig:reg_lang_pumping_lemma} + \begin{center} + \begin{tikzpicture}[->] + \node[state, initial] (q1) {$q_1$}; + \node[state, right = 2 of q1] (q2) {$q_2$}; + \node[state, accepting, right = 2 of q2] (q3) {$q_3$}; + \node[state, above = 2 of q2] (q4) {$q_4$}; + \draw (q1) edge[above, snake it] node{} (q2) + (q2) edge[bend right, snake it, side by side={red}{blue}] node{} (q4) + (q4) edge[bend right, snake it, color=blue] node[left]{$y$} (q2) + (q4) edge[above, snake it, color=green] node[right]{$z$} (q3) + (q1) edge[above, snake it, color=red] node{$x$} (q2) + ; + \end{tikzpicture} + \end{center} + +\end{figure} + + +\section{Замкнутость регулярных языков относительно операций} + +\begin{theorem} + Регулярные языки замкнуты относительно перечисленных ниже операций. + \begin{enumerate} + \item Пересечение + \item Дополнение + \item Обращение + \item Разность + \end{enumerate} +\end{theorem} + +Линейная алгебра для работы с регулярными языками: пересечение, замыкание. + +Построение пересечения через тензорное произведение автоматов. + +Идея доказательства, что мы построили именно пересечение. + +Пересечение через синхронный обход в ширину. + +%\section{Вопросы и задачи} +% +%Построить базу. +% +%Научиться выполнять запросы через линейку. diff --git a/tex/main.tex b/tex/main.tex index 27d6929..c2ee782 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -48,6 +48,7 @@ \input{LinearAlgebra} \input{GraphTheoryIntro} \input{FormalLanguageTheoryIntro} +\input{RegularLanguages} \backmatter \setchapterstyle{plain} diff --git a/tex/styles/theorems.tex b/tex/styles/theorems.tex index 3490597..90cea4e 100644 --- a/tex/styles/theorems.tex +++ b/tex/styles/theorems.tex @@ -16,7 +16,7 @@ headpunct=., postheadspace=5pt plus 1pt minus 1pt,]{myStyleWithFrame} \declaretheoremstyle[spacebelow=\topsep, - headfont=\bfseries\sffamily, + headfont=\itshape\sffamily, bodyfont=\normalfont, headpunct=., postheadspace=5pt plus 1pt minus 1pt, @@ -36,21 +36,21 @@ right = 0.5mm } -% \tcolorboxenvironment{theorem}{} +\tcolorboxenvironment{theorem}{} % \tcolorboxenvironment{theorem*}{} % \tcolorboxenvironment{axiom}{} % \tcolorboxenvironment{assertion}{} -% \tcolorboxenvironment{lemma}{} +\tcolorboxenvironment{lemma}{} % \tcolorboxenvironment{proposition}{} % \tcolorboxenvironment{corollary}{} \tcolorboxenvironment{definition}{} % \tcolorboxenvironment{proofReplace}{toprule=0mm,bottomrule=0mm,rightrule=0mm, colback=white, breakable } -% \declaretheorem[name=Теорема, numberwithin=chapter, style=myStyleWithFrame]{theorem} +\declaretheorem[name=Теорема, numberwithin=chapter, style=myStyleWithFrame]{theorem} % \declaretheorem[name=Теорема, numbered=no, style=myStyleWithFrame]{theorem*} % \declaretheorem[name=Аксиома, sibling=theorem, style=myStyleWithFrame]{axiom} % \declaretheorem[name=Преположение, sibling=theorem, style=myStyleWithFrame]{assertion} -% \declaretheorem[name=Лемма, sibling=theorem, style=myStyleWithFrame]{lemma} +\declaretheorem[name=Лемма, sibling=theorem, style=myStyleWithFrame]{lemma} % \declaretheorem[name=Предложение, sibling=theorem, style=myStyleWithFrame]{proposition} % \declaretheorem[name=Следствие, numberwithin=theorem, style=myStyleWithFrame]{corollary} @@ -64,3 +64,5 @@ % \declaretheorem[name=Доказательство, numbered=no, style=myProofStyleWithFrame]{proofReplace} % \renewenvironment{proof}[1][\proofname]{\begin{proofReplace}}{\end{proofReplace}} % \declaretheorem[name=Доказательство, numbered=no, style=myProofStyleWithFrame]{longProof} + +\declaretheorem[name={Набросок доказательства}, numbered=no, style=myProofStyleWithFrame]{proofSketch} diff --git a/tex/styles/tikz.tex b/tex/styles/tikz.tex index 704f667..e91a454 100644 --- a/tex/styles/tikz.tex +++ b/tex/styles/tikz.tex @@ -4,8 +4,20 @@ \usetikzlibrary{positioning} \usetikzlibrary{shapes.geometric} \usetikzlibrary{automata} +\usetikzlibrary{decorations.pathmorphing} \tikzsetexternalprefix{figures/externalized/} +% Required in RegularLanguages +\tikzset{snake it/.style={decorate, decoration=snake}} +\tikzset{ + side by side/.style 2 args={ + line width=2pt, + #1, + postaction={ + clip,postaction={draw,#2} + } + } +} + % \usetikzlibrary{fit, calc} -% \usetikzlibrary{decorations.pathmorphing} From b340a7e91bd799a51eec94282db7558e99b013ea Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Wed, 19 Jun 2024 20:57:19 +0300 Subject: [PATCH 21/29] Add CFL chapter --- tex/Context-Free_Languages.tex | 576 +++++++++++++++++++++++++++++++++ tex/figures/cfl/pumping0.tex | 26 ++ tex/figures/cfl/pumping1.tex | 34 ++ tex/figures/cfl/pumping2.tex | 40 +++ tex/figures/cfl/tree0.tex | 27 ++ tex/main.tex | 1 + tex/styles/math.tex | 1 + tex/styles/theorems.tex | 4 +- tex/styles/utils.tex | 1 + 9 files changed, 708 insertions(+), 2 deletions(-) create mode 100644 tex/Context-Free_Languages.tex create mode 100644 tex/figures/cfl/pumping0.tex create mode 100644 tex/figures/cfl/pumping1.tex create mode 100644 tex/figures/cfl/pumping2.tex create mode 100644 tex/figures/cfl/tree0.tex diff --git a/tex/Context-Free_Languages.tex b/tex/Context-Free_Languages.tex new file mode 100644 index 0000000..0581e04 --- /dev/null +++ b/tex/Context-Free_Languages.tex @@ -0,0 +1,576 @@ +\setchapterpreamble[u]{\margintoc} +\chapter{Контекстно-свободные языки и грамматики} +\label{CFG} + +Из всего многообразия нас будут интересовать прежде всего контекстно-свободные грамматики. + +\begin{definition}[Контекстно-свободная грамматика] + \emph{Контекстно-свободная грамматика}~--- это четвёрка вида $\langle \Sigma, N, P, S \rangle$, где + \begin{itemize} + \item $\Sigma$~--- это терминальный алфавит; + \item $N$~--- это нетерминальный алфавит; + \item $P$~--- это множество правил (продукций), таких что каждая продукция имеет вид $N_i \to \alpha$, где $N_i \in N$ и $\alpha \in \{\Sigma \cup N\}^* \cup {\varepsilon}$; + \item $S$~--- стартовый нетерминал. + Отметим, что $\Sigma \cap N = \varnothing$. + \end{itemize} +\end{definition} + +\begin{example} + \label{ex:binary_cfg} + Грамматика, задающая язык целых чисел в двоичной записи без лидирующих нулей: $G = \langle \{0, 1, -\}, \{S, N, A\}, P, S \rangle$, где $P$ определено следующим образом: + \begin{align*} + S & \rightarrow 0 \mid N \mid - N \\ + N & \rightarrow 1 A \\ + A & \rightarrow 0 A \mid 1 A \mid \varepsilon + \end{align*} +\end{example} + +При спецификации грамматики часто опускают множество терминалов и нетерминалов, оставляя только множество правил. +При этом нетерминалы часто обозначаются прописными латинскими буквами, терминалы~--- строчными, а стартовый нетерминал обозначается буквой $S$. +Мы будем следовать этим обозначениям, если не указано иное. + +\begin{definition}[Отношение непосредственной выводимости] + \label{def derivability in CFG} + \emph{Отношение непосредственной выводимости}. Мы говорим, что последовательность терминалов и нетерминалов $\gamma \beta \delta$ \emph{непосредственно выводится из} $\gamma \alpha \delta$ \emph{при помощи правила} $\alpha \rightarrow \beta$ ($\gamma \alpha \delta \derives[] \gamma \beta \delta$), если + \begin{itemize} + \item $\alpha \rightarrow \beta \in P$, + \item $\gamma, \delta \in \{\Sigma \cup N\}^* \cup {\varepsilon}$. + \end{itemize} +\end{definition} + +\begin{definition}[Рефлексивно-транзитивное замыкание отношения] + \emph{Рефлексивно-транзитивное замыкание отношения}~--- это наименьшее рефлексивное и транзитивное отношение, содержащее исходное. +\end{definition} + +\begin{definition}[Отношение выводимости] + \emph{Отношение выводимости} является рефлексивно-транзитивным замыканием отношения непосредственной выводимости; обозначается $\derives$. + \begin{itemize} + \item $\alpha \derives \beta$ означает $\exists \gamma_0, \dots, \gamma_k \in \{\Sigma \cup N\}^* \cup {\varepsilon}$: + \[ \alpha \derives[] \gamma_0 \derives[] \gamma_1 \derives[] \dots \derives[] \gamma_{k-1} \derives[] \gamma_{k} \derives[] \beta;\] + \item Транзитивность: $\forall \alpha, \beta, \gamma \in \{\Sigma \cup N\}^* \cup {\varepsilon}$: $\alpha \derives \beta$, $\beta \derives \gamma \derives[] \alpha \derives \gamma$; + \item Рефлексивность: $\forall \alpha \in \{\Sigma \cup N\}^* \cup {\varepsilon}$: $\alpha \derives \alpha$; + \item $\alpha \derives \beta$~--- $\alpha$ выводится из $\beta$; + \item $\alpha \derives[k] \beta$~--- $\alpha$ выводится из $\beta$ за $k$ шагов; + \item $\alpha \derives[+] \beta$~--- при выводе использовалось хотя бы одно правило грамматики. + \end{itemize} +\end{definition} + +\begin{example} + Пример вывода цепочки $-1101$ в грамматике из примера~\ref{ex:binary_cfg}: + \[ + S \derives[] - N \derives[] - 1 A \derives[] - 1 1 A \derives - 1 1 0 1 A \derives[] - 1 1 0 1 + \] +\end{example} + +\begin{definition}[Вывод слова в грамматике] + Слово $\omega \in \Sigma^*$ \emph{выводимо в грамматике} $\langle \Sigma, N, P, S \rangle$, если существует некоторый вывод этого слова из начального нетерминала $S \derives \omega$. + +\end{definition} + +\begin{definition}[Левосторонний вывод] + \emph{Левосторонний вывод}. На каждом шаге вывода заменяется самый левый нетерминал. +\end{definition} + +\begin{definition}[Правосторонний вывод] + \emph{Правосторонний вывод}. На каждом шаге вывода заменяется самый правый нетерминал. +\end{definition} + +\begin{example} + Приведем пример левостороннего вывода цепочки $cbaa$ в грамматике: + \begin{align*} + S & \rightarrow A A \mid s \\ + A & \rightarrow A A \mid B b \mid a \\ + B & \rightarrow c \mid d + \end{align*} + Жирным выделен нетерминал, заменяемый на каждом шагу вывода. + \[ \mathbf{S} \derives[] \mathbf{A} A \derives[] \mathbf{B} b A \derives[] c b \mathbf{A} \derives[] c b \mathbf{A} A \derives[] c b a \mathbf{A} \derives[] c b a a \] +\end{example} + +Аналогично левостороннему можно определить правосторонний вывод. + +\begin{definition}[Язык] + \emph{Язык, задаваемый грамматикой}~--- множество строк, выводимых в грамматике $L(G) = \{ \omega \in \Sigma^* \mid S \derives \omega \}$. +\end{definition} + +\begin{definition}[Эквивалентные грамматики] + Грамматики $G_1$ и $G_2$ называются \emph{эквивалентными}, если они задают один и тот же язык: $L(G_1) = L(G_2)$ +\end{definition} + +\begin{example} Пример эквивалентных грамматик для языка целых чисел в двоичной системе счисления. + + \begin{tabular}{p{0.4\textwidth} | p{0.5\textwidth}} + \[ + \begin{aligned} + \Sigma & = \{ 0, 1, - \} \\ + N & = \{ S, N, A \} \\~\\ + S & \rightarrow 0 \mid N \mid - N \\ + N & \rightarrow 1 A \\ + A & \rightarrow 0 A \mid 1 A \mid \varepsilon \\ + \end{aligned} + \] + & + \[ + \begin{aligned} + \Sigma & = \{ 0, 1, - \} \\ + N & = \{ S, A \} \\~\\ + S & \rightarrow 0 \mid 1 A \mid - 1 A \\ + A & \rightarrow 0 A \mid 1 A \mid \varepsilon \\ + \end{aligned} + \] + \end{tabular} + +\end{example} + + +\begin{definition}[Неоднозначная грамматика] + \emph{Неоднозначная грамматика}~--- грамматика, в которой существует 2 и более левосторонних (правосторонних) выводов для одного слова. +\end{definition} + +\begin{example} + Неоднозначная грамматика для правильных скобочных последовательностей: + \[ + S \to (S) \mid S S \mid \varepsilon + \] + Два различных левосторонних вывода строки $()()()$: + \begin{gather*} + S \derives[] S S \derives [] (S) S \derives[] () S \derives[] () S S \derives[] () (S) S \derives[] () () S \derives[] () () (S) \derives[] () () ()\\ + S \derives[] S S \derives[] S S S \derives[] (S) S S \derives[] () S S \derives[] () (S) S \derives[] () () S \derives[] () () (S) \derives[] () () () + \end{gather*} +\end{example} + +\begin{definition}[Однозначная грамматика] + \emph{Однозначная грамматика}~--- грамматика, в которой существует не более одного левостороннего (правостороннего) вывода для каждого слова. +\end{definition} + +\begin{example} + Однозначная грамматика для правильных скобочных последовательностей + \[ + S \to (S)S \mid \varepsilon + \] +\end{example} + +\begin{definition}[Существенно неоднозначный язык] + \emph{Существенно неоднозначные языки}~--- языки, для которых невозможно построить однозначную грамматику. +\end{definition} + +\begin{example} + Пример существенно неоднозначного языка + \[\{a^n b^n c^m \mid n, m \in \BbbZ\} \cup \{a^n b^m c^m \mid n,m \in \BbbZ\}\] +\end{example} + +\section{Дерево вывода} +\label{sect:DerivTree} + +В некоторых случаях не достаточно знать порядок применения правил. +Необходимо структурное представление вывода цепочки в грамматике. +Таким представлением является \emph{дерево вывода}. + +\begin{definition}[Дерево вывода] + Деревом вывода цепочки $\omega$ в грамматике $G = \langle \Sigma, N, S, P \rangle$ называется дерево, удовлетворяющее следующим свойствам. + \begin{enumerate} + \item Помеченное: метка каждого внутреннего узла~--- нетерминал, метка каждого листа~--- терминал или $\varepsilon$. + \item Корневое: корень помечен стартовым нетерминалом. + \item Упорядоченное. + \item В дереве может существовать узел с меткой $N_i$ и сыновьями $M_j \dots M_k$ только тогда, когда в грамматике есть правило вида $N_i \to M_j \dots M_k$. + \item Крона образует исходную цепочку $\omega$. + \end{enumerate} +\end{definition} + +\begin{example} + Построим дерево вывода цепочки $ababab$ в грамматике + \[ G = \langle \{a,b\}, \{S\}, S, \{S \to a \ S \ b \ S, S \to \varepsilon\} \rangle.\] + \begin{center} + \input{figures/cfl/tree0.tex} + \end{center} +\end{example} + +\begin{theorem} + Пусть $G = \langle \Sigma, N, P, S \rangle$~--- КС-грамматика. + Вывод $S \derives \alpha$, где $\alpha \in (N \cup \Sigma)^*, \alpha \neq \varepsilon$ существует $\Leftrightarrow$ существует дерево вывода в грамматике $G$ с кроной $\alpha$. +\end{theorem} + +\section{Пустота КС-языка} + +\begin{theorem} + Существует алгоритм, определяющий, является ли язык, порождаемый КС грамматикой, пустым. +\end{theorem} + +\begin{proof} + Следующая лемма утверждает, что если в КС языке есть выводимое слово, то существует другое выводимое слово с деревом вывода не глубже количества нетерминалов грамматики. + Для доказательства теоремы достаточно привести алгоритм, последовательно строящий все деревья глубины не больше количества нетерминалов грамматики, и проверяющий, являются ли такие деревья деревьями вывода. + Если в результате работы алгоритма не удалось построить ни одного дерева, то грамматика порождает пустой язык. +\end{proof} + +\begin{lemma} + Если в данной грамматике выводится некоторая цепочка, то существует цепочка, дерево вывода которой не содержит ветвей длиннее $m$, где $m$~--- количество нетерминалов грамматики. +\end{lemma} + +\begin{proof} + Рассмотрим дерево вывода цепочки $\omega$. Если в нем есть 2 узла, соответствующих одному нетерминалу A, обозначим их $n_1$ и $n_2$. + + Предположим, $n_1$ расположен ближе к корню дерева, чем $n_2$. + + Вывод цепочки $\omega$ имеет следующий вид: + \[S \derives \alpha A_{n_1} \beta \derives \alpha \omega_1 \beta; S \derives \alpha \gamma A_{n_2} \delta \beta \derives \alpha \gamma \omega_2 \delta \beta \derives \omega,\] + при этом $\omega_2$ является подцепочкой $\omega_1$. + + Заменим в изначальном дереве узел $n_1$ на $n_2$. Полученное дерево является деревом вывода цепочки $\alpha \omega_2 \delta$. + + Повторяем процесс замены одинаковых нетерминалов до тех пор, пока в дереве не останутся только уникальные нетерминалы. + + В полученном дереве не может быть ветвей длины большей, чем $m$. + + По построению оно является деревом вывода. +\end{proof} + + +\section{Нормальная форма Хомского} +\label{section:CNF} + +\begin{definition}[Нормальная форма Хомского] + Контекстно-свободная грамматика $\langle \Sigma, N, P, S\rangle$ находится в \emph{Нормальной Форме Хомского}, если она содержит только правила следующего вида: + \begin{itemize} + \item $A \to B C$, где $A, B, C \in N$, а стартовый нетерминал $S$ не содержится в правой части правила. + \item $A \to a$, где $A \in N$, $a \in \Sigma$. + \item $S \to \varepsilon$: только из стартового нетерминала выводима пустая строка. + \end{itemize} +\end{definition} + +\begin{theorem} + Любую КС грамматику можно преобразовать в НФХ. +\end{theorem} + +\begin{proof} + Алгоритм преобразования в НФХ состоит из следующих шагов: + \begin{itemize} + \item Замена неодиночных терминалов + \item Удаление длинных правил + \item Удаление $\varepsilon$-правил + \item Удаление цепных правил + \item Удаление бесполезных нетерминалов + \end{itemize} + То, что каждый из этих шагов преобразует грамматику к эквивалентной, при этом является алгоритмом, доказано в следующих леммах. +\end{proof} + +\begin{lemma} + Для любой КС-грамматики можно построить эквивалентную, которая не содержит правила с неодиночными терминалами. +\end{lemma} + +\begin{proof} + Каждое правило $A \to B_0 B_1 \dots B_k$, $k \geq 1$ заменить на множество правил, где $C_i$~--- новый нетерминал: + \begin{align*} + A & \to C_0 C_1 \dots C_k \\ + C_0 & \to B_0 \\ + C_1 & \to B_1 \\ + & \dots \\ + C_k & \to B_k + \end{align*} +\end{proof} + +\begin{lemma} + Для любой КС-грамматики можно построить эквивалентную, которая не содержит правил длины больше 2. +\end{lemma} + +\begin{proof} + Каждое правило $A \to B_0 B_1 \dots B_k$, $k \geq 2$ заменить на множество правил: + \begin{align*} + A & \to B_0 C_0 \\ + C_0 & \to B_1 C_1 \\ + & \dots \\ + C_{k-3} & \to B_{k-2} C_{k-2} \\ + C_{k-2} & \to B_{k-1} B_k + \end{align*} +\end{proof} + + +\begin{lemma} + Для любой КС-грамматики можно построить эквивалентную, не содержащую $\varepsilon$-правил. +\end{lemma} + +\begin{proof} + Рекурсивно определим $\varepsilon$-правила: + \begin{itemize} + \item $A \to \varepsilon$~--- $\varepsilon$-правило + \item $A \to B_0 \dots B_k$~--- $\varepsilon$-правило, если $\forall i$: $B_i$~--- $\varepsilon$-правило. + \end{itemize} + Каждое правило $A \to B_0 B_1 \dots B_k$ заменяем на множество правил, где каждое $\varepsilon$-правило удалено во всех возможных комбинациях. +\end{proof} + +\begin{lemma} + Для любой КС-грамматики можно построить эквивалентную, не содержащую цепные правила. +\end{lemma} + +\begin{proof} + \emph{Цепное правило}~--- правило вида $A \to B\text{, где } A, B \in N$. + \emph{Цепная пара}~--- упорядоченная пара $(A,B)$, в которой $A\derives B$, используя только цепные правила. + + Алгоритм: + \begin{enumerate} + \item Найти все цепные пары в грамматике $G$. + Найти все цепные пары можно по индукции: + Базис: $(A,A)$~--- цепная пара для любого нетерминала, так как $A\derives A$ за ноль шагов. + Индукция: Если пара $(A,B_0)$~--- цепная, и есть правило $B_0 \to B_1$, то $(A,B_1)$~--- цепная пара. + \item Для каждой цепной пары $(A,B)$ добавить в грамматику $G'$ все правила вида $A \to a$, где $B \to a$~--- нецепное правило из $G$. + \item Удалить все цепные правила + \end{enumerate} + Пусть $G$~--- контекстно-свободная грамматика. $G'$~--- грамматика, полученная в результате применения алгоритма к $G$. Тогда $L(G)=L(G')$. +\end{proof} + +\begin{definition}[Порождающий и непорождающий нетерминалы] + Нетерминал $A$ называется \emph{порождающим}, если из него может быть выведена конечная терминальная цепочка. + Иначе он называется \emph{непорождающим}. +\end{definition} + +\begin{lemma} + Можно удалить все бесполезные (непорождающие) нетерминалы. +\end{lemma} + +\begin{proof} + После удаления из грамматики правил, содержащих непорождающие нетерминалы, язык не изменится, так как непорождающие нетерминалы по определению не могли участвовать в выводе какого-либо слова. + + Алгоритм нахождения порождающих нетерминалов: + \begin{enumerate} + \item Множество порождающих нетерминалов пустое. + \item Найти правила, не содержащие нетерминалов в правых частях и добавить нетерминалы, встречающихся в левых частях таких правил, в множество. + \item Если найдено такое правило, что все нетерминалы, стоящие в его правой части, уже входят в множество, то добавить в множество нетерминалы, стоящие в его левой части. + \item Повторить предыдущий шаг, если множество порождающих нетерминалов изменилось. + \end{enumerate} + В результате получаем множество всех порождающих нетерминалов грамматики, а все нетерминалы, не попавшие в него, являются непорождающими. + Их можно удалить. +\end{proof} + +\begin{example} + Приведем в Нормальную Форму Хомского однозначную грамматику правильных скобочных последовательностей: $S \to a S b S \mid \varepsilon$ + + Первым шагом добавим новый нетерминал и сделаем его стартовым: + \begin{align*} + S_0 & \to S \\ + S & \to a S b S \mid \varepsilon + \end{align*} + Заменим все терминалы на новые нетерминалы: + \begin{align*} + S_0 & \to S \\ + S & \to L S R S \mid \varepsilon \\ + L & \to a \\ + R & \to b + \end{align*} + Избавимся от длинных правил: + \begin{align*} + S_0 & \to S \\ + S & \to L S' \mid \varepsilon \\ + S' & \to S S'' \\ + S'' & \to R S \\ + L & \to a \\ + R & \to b + \end{align*} + Избавимся от $\varepsilon$-продукций: + \begin{align*} + S_0 & \to S \mid \varepsilon \\ + S & \to L S' \\ + S' & \to S'' \mid S S'' \\ + S'' & \to R \mid R S \\ + L & \to a \\ + R & \to b + \end{align*} + Избавимся от цепных правил: + \begin{align*} + S_0 & \to L S' \mid \varepsilon \\ + S & \to L S' \\ + S' & \to b \mid R S \mid S S'' \\ + S'' & \to b \mid R S \\ + L & \to a \\ + R & \to b + \end{align*} +\end{example} + +\begin{definition}[Ослабленная нормальная форма Хомского] + \label{defn:wCNF} + Контекстно-свободная грамматика $\langle \Sigma, N, P, S\rangle$ находится в \emph{ослабленной Нормальной Форме Хомского}, если она содержит только правила следующего вида: + \begin{itemize} + \item $A \to B C$, где $A, B, C \in N$; + \item $A \to a$, где $A \in N$, $a \in \Sigma$; + \item $A \to \varepsilon$, где $A \in N$. + \end{itemize} + + То есть ослабленная НФХ отличается от НФХ тем, что: + \begin{enumerate} + \item $\varepsilon$ может выводиться из любого нетерминала; + \item $S$ может появляться в правых частях правил. + \end{enumerate} +\end{definition} + +\section{Лемма о накачке} + +\begin{lemma} + Пусть $L$~--- контекстно-свободный язык над алфавитом $\Sigma$, тогда существует такое $n$, что для любого слова $\omega \in L$, $|\omega| \geq n$ найдутся слова $u,v,x,y,z\in \Sigma^*$, для которых верно: $uvxyz = \omega, vy\neq \varepsilon,|vxy|\leq n$ и для любого $k \geq 0$ $uv^kxy^kz \in L$. +\end{lemma} + +\begin{proofSketch} + \begin{enumerate} + \item Для любого КС языка можно найти грамматику в нормальной форме Хомского. + \item Очевидно, что если брать достаточно длинные цепочки, то в дереве вывода этих цепочек, на пути от корня к какому-то листу обязательно будет нетерминал, встречающийся минимум два раза. Если $m$~--- количество нетерминалов в НФХ, то длины $2^{m+1}$ должно хватить. Это и будет $n$ из леммы. + \item Возьмём путь, на котором есть хотя бы дважды повторяется некоторый нетерминал. Скажем, это нетерминал $N_1$. Пойдём от листа по этому пути. Найдём первое появление $N_1$. Цепочка, задаваемая поддеревом для этого узла~--- это $x$ из леммы. + \item Пойдём дальше и найдём второе появление $N_1$. Цепочка, задаваемая поддеревом для этого узла~--- это $vxy$ из леммы. + \item Теперь мы можем копировать кусок дерева между этими повторениями $N_1$ и таким образом накачивать исходную цепочку. + \end{enumerate} + Надо только проверить выполнение ограничений на длины. + Нахождение разбиения и пример накачки продемонстрированы на рисунках~\ref{fig:pumping1} и~\ref{fig:pumping2}. +\end{proofSketch} + +\begin{figure} + \centering + \input{figures/cfl/pumping1.tex} + \caption{Разбиение цепочки для леммы о накачке} + \label{fig:pumping1} +\end{figure} + +\begin{figure} + \centering + \begin{subfigure}[b]{0.4\textwidth} + \centering + \input{figures/cfl/pumping0.tex} + \caption{$k = 0$.} + % \label{fig:f1} + \end{subfigure} + \hfill + \begin{subfigure}[b]{0.4\textwidth} + \centering + \input{figures/cfl/pumping2.tex} + \caption{$k = 2$.} + % \label{fig:f2} + \end{subfigure} + \caption{Пример накачки цепочки с рисунка~\ref{fig:pumping1}} + \label{fig:pumping2} +\end{figure} + +Для примера предлагается проверить неконтекстно-свободность языка $L=\{a^nb^nc^n \mid n>0\}$. + +\section{Замкнутость КС языков относительно операций} + +\begin{theorem} + Контекстно-свободные языки замкнуты относительно следующих операций: + \begin{enumerate} + \item Объединение: если $L_1$ и $L_2$~--- контекстно-свободные языки, то и $L_3 = L_1 \cup L_2$~--- контекстно-свободный. + \item Конкатенация: если $L_1$ и $L_2$~--- контекстно-свободные языки, то и $L_3 = L_1 \cdot L_2$~--- контекстно-свободный. + \item Замыкание Клини: если $L_1$~--- контекстно-свободный, то и $L_2 = \bigcup\limits_{i=0}^{\infty} L_1^i $~--- контекстно-свободный. + \item Разворот: если $L_1$~--- контекстно-свободный, то и $L_2 = {L_1}^r = \{ l^r \mid l \in L_1\}$ является контекстно-свободным. + \item Пересечение с регулярными языками: если $L_1$~--- контекстно-свободный, а $L_2$~--- регулярный, то $L_3 = L_1 \cap L_2$~--- контекстно-свободный. + \item Разность с регулярными языками: если $L_1$~--- контекстно-свободный, а $L_2$~--- регулярный, то $L_3 = L_1 \setminus L_2$~--- контекстно-свободный. + \end{enumerate} +\end{theorem} +\begin{proof} + Для доказательства пунктов 1--4 можно построить КС грамматику нового языка имея грамматики для исходных. + Будем предполагать, что множества нетерминальных символов различных грамматик для исходных языков не пересекаются. + \begin{enumerate} + \item $G_1=\langle\Sigma_1,N_1,P_1,S_1\rangle$~--- грамматика для $L_1$, $G_1=\langle\Sigma_2,N_2,P_2,S_2\rangle$~--- грамматика для $L_2$, тогда $G_3=\langle\Sigma_1 \cup \Sigma_2, N_1 \cup N_2 \cup \{S_3\}, P_1 \cup P_2 \cup \{S_3 \to S_1 \mid S_2\} ,S_3\rangle$~--- грамматика для $L_3$. + \item $G_1=\langle\Sigma_1,N_1,P_1,S_1\rangle$~--- грамматика для $L_1$, $G_1=\langle\Sigma_2,N_2,P_2,S_2\rangle$~--- грамматика для $L_2$, тогда $G_3=\langle\Sigma_1 \cup \Sigma_2, N_1 \cup N_2 \cup \{S_3\}, P_1 \cup P_2 \cup \{S_3 \to S_1 S_2\} ,S_3\rangle$~--- грамматика для $L_3$. + \item $G_1=\langle\Sigma_1,N_1,P_1,S_1\rangle$~--- грамматика для $L_1$, тогда $G_2=\langle\Sigma_1, N_1 \cup \{S_2\}, P_1 \cup \{S_2 \to S_1 S_2\ \mid \varepsilon\}, S_2\rangle$~--- грамматика для $L_2$. + \item $G_1=\langle\Sigma_1,N_1,P_1,S_1\rangle$~--- грамматика для $L_1$, тогда $G_2=\langle\Sigma_1, N_1, \{N^i \to \omega^R \mid N^i \to \omega \in P_1 \}, S_1\rangle$~--- грамматика для $L_2$. + \end{enumerate} + + Чтобы доказать замкнутость относительно пересечения с регулярными языками, построим по КС грамматике рекурсивный автомат $R_1$, по регулярному выражению~--- детерминированный конечный автомат $R_2$, и построим их прямое произведение $R_3$. + Переходы по терминальным символам в новом автомате возможны тогда и только тогда, когда они возможны одновременно и в исходном рекурсивном автомате и в исходном конечном. + За рекурсивные вызовы отвечает исходный рекурсивный автомат. + \marginnote{TODO: Вот тут RSM очень внезапно вылез} + Значит цепочка принимается $R_3$ тогда и только тогда, когда она принимается одновременно $R_1$ и $R_2$: так как состояния $R_3$~--- это пары из состояния $R_1$ и $R_2$, то по трассе вычислений $R_3$ мы всегда можем построить трассу для $R_1$ и $R_2$ и наоборот. + + Чтобы доказать замкнутость относительно разности с регулярным языком, достаточно вспомнить, что регулярные языки замкнуты относительно дополнения, и выразить разность через пересечение с дополнением: + \[L_1 \setminus L_2 = L_1 \cap \overline{L_2} \qedhere\] +\end{proof} + +\begin{theorem} + Контекстно-свободные языки не замкнуты относительно следующих операций: + \begin{enumerate} + \item Пересечение: если $L_1$ и $L_2$~--- контекстно-свободные языки, то и $L_3 = L_1 \cap L_2$~--- не контекстно-свободный. + \item Разность: если $L_1$ и $L_2$~--- контекстно-свободные языки, то и $L_3 = L_1 \setminus L_2$~--- не контекстно-свободный. + \end{enumerate} +\end{theorem} + +\begin{proof} + Чтобы доказать незамкнутость относительно пресечения, рассмотрим языки $L_1 = \{a^n b^n c^k \mid n \geq 0, k \geq 0\}$ и $L_2 = \{a^k b^n c^n \mid n \geq 0, k \geq 0\}$. + Очевидно, что $L_1$ и $L_2$~--- контекстно-свободные языки. + Рассмотрим $L_3 = L_1 \cap L_2 = \{a^n b^n c^n \mid n \geq 0\}$. + $L_3$ не является контекстно-свободным по лемме о накачке для контекстно-свободных языков. + + Чтобы доказать незамкнутость относительно разности проделаем следующее. + \begin{enumerate} + \item Рассмотрим языки $L_4 = \{a^m b^n c^k \mid m \neq n, k \geq 0\}$ и $L_5 = \{a^m b^n c^k \mid n \neq k, m \geq 0\}$. + Эти языки являются контекстно-свободными. + Это легко заметить, если знать, что язык $L'_4 = \{a^m b^n c^k \mid 0 \leq m < n, k \geq 0\}$ задаётся следующей грамматикой: + \begin{align*} + S & \to S c & T & \to a T b \\ + S & \to T & T & \to T b \\ + & & T & \to b. + \end{align*} + \item Рассмотрим язык $L_6 = \overline{L'_6} = \overline{\{a^n b^m c^k \mid n \geq 0, m \geq 0, k \geq 0\}}$. + Данный язык является регулярным. + \item Рассмотрим язык $L_7 = L_4 \cup L_5 \cup L_6$~--- контекстно-свободный, так как является объединением контекстно-свободных. + \item Рассмотрим $\overline{L_7} = \{a^n b^n c^n \mid n \geq 0\} = L_3$: $L_4$ и $L_5$ задают языки с правильным порядком символов, но неравным их количеством, $L_6$ задаёт язык с неправильным порядком символов. + Из предыдущего пункта мы знаем, что $L_3$ не является контекстно-свободным. + \qedhere + \end{enumerate} +\end{proof} + +\section{Рекурсивные автоматы и сети} + +Рекурсивный автомат или сеть~--- это представление контекстно-свободных грамматик, обобщающее конечные автоматы. +В нашей работе мы будем придерживаться термина \emph{рекурсивный автомат}. +Классическое определение рекурсивного автомата выглядит следующим образом. + +\begin{definition} + Рекурсивный автомат~--- это кортеж вида $\langle N, \Sigma, S, D \rangle$, где + \begin{itemize} + \item $N$~--- нетерминальный алфавит; + \item $\Sigma$~--- терминальный алфавит; + \item $S$~--- стартовый нетерминал; + \item $D$~--- конечный автомат над $N \cup \Sigma$ в котором стартовые и финальные состояния помечены подмножествами $N$. + \end{itemize} +\end{definition} + +Построение РКА по грамматике. + +Допущение о том, что все состояния занумерованы подряд и уникальны. + +Немного ссылок на работы по РКА. + +Построим рекурсивный автомат для грамматики $G$: +\begin{align*} + S & \to a S b \\ + S & \to a b +\end{align*} + +\begin{figure} + \caption{Пример рекурсивного автомата для грамматики $G$.} + \label{input1} + \begin{tikzpicture}[node distance=2.5cm,shorten >=1pt,on grid,auto] + \node[state, initial] (q_0) {$0 \{S\}$}; + \node[state] (q_1) [right=of q_0] {$1$}; + \node[state] (q_2) [right=of q_1] {$2$}; + \node[state, accepting] (q_3) [right=of q_2] {$3\{S\}$}; + \path[->] + (q_0) edge node {a} (q_1) + (q_1) edge node {S} (q_2) + (q_2) edge node {b} (q_3) + (q_1) edge[bend left, above] node {b} (q_3); + \end{tikzpicture} +\end{figure} + + +Используем стандартные обозначения для стартовых и финальных состояний. +Дополнительно в стартовых и финальных состояниях укажем нетерминалы, для которых эти состояния стартовые/финальные. + +В некоторых случаях рекурсивный автомат можно рассматривать как конечный автомат над смешанным алфавитом. +Именно такой взгляд мы будем использовать при изложении алгоритма. + +Пример интерпретации конечного автомата. + + + +%\section{Вопросы и задачи} +%\begin{enumerate} +% \item Постройте дерево вывода цепочки $w=aababb$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ S \}, S \rangle$. +% \item Постройте все левосторонние выводы цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$. +% \item Постройте все правосторонние выводы цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$. +% \item \label{t1}Постройте все деревья вывода цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$, соответствующие левосторонним выводам. +% \item \label{t2}Постройте все деревья вывода цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$, соответствующие правосторонним выводам. +%\end{enumerate} diff --git a/tex/figures/cfl/pumping0.tex b/tex/figures/cfl/pumping0.tex new file mode 100644 index 0000000..5c1e05a --- /dev/null +++ b/tex/figures/cfl/pumping0.tex @@ -0,0 +1,26 @@ + +\begin{tikzpicture} + \node[draw=none, fill=none] at (0, 4) {S}; + \node[draw=none, fill=none] at (0.1, 1) {A}; + + \draw (-1,0) -- (0,3.8); + \draw (0,3.8) -- (1,0); + + \draw (-0.5,0) -- (0.1,0.8); + \draw (0.1,0.8) -- (0.5,0); + + \fill[Orchid] (-1,-0.5) rectangle ++(0.5,0.5); + \fill[LimeGreen] (-0.5,-0.5) rectangle ++(1,0.5); + \fill[Turquoise] (0.5,-0.5) rectangle ++(0.5,0.5); + + \draw[draw=black] (-1,-0.5) rectangle ++(2,0.5); + \draw[draw=black] (-0.5,-0.5) rectangle ++(1,0.5); + + \draw [thick,densely dotted, rounded corners=1mm] (0,3.8) -- (-0.1, 2.5) -- (0.15, 1.4) -- (0.1, 1.1); + + + \node[draw=none, fill=none] at (-0.75,-0.25) {$u$}; + \node[draw=none, fill=none] at (0,-0.25) {$w$}; + \node[draw=none, fill=none] at (0.75,-0.25) {$y$}; +\end{tikzpicture} + diff --git a/tex/figures/cfl/pumping1.tex b/tex/figures/cfl/pumping1.tex new file mode 100644 index 0000000..02cd0b6 --- /dev/null +++ b/tex/figures/cfl/pumping1.tex @@ -0,0 +1,34 @@ + +\begin{tikzpicture} + \node[draw=none, fill=none] at (0, 4) {S}; + \node[draw=none, fill=none] at (-0.1, 2.3) {A}; + \node[draw=none, fill=none] at (0.1, 1) {A}; + + \draw (-1.5,0) -- (0,3.8); + \draw (0,3.8) -- (1.5,0); + \draw (-1,0) -- (-0.1,2.1); + \draw (-0.1,2.1) -- (1,0); + \draw (-0.5,0) -- (0.1,0.8); + \draw (0.1,0.8) -- (0.5,0); + + \fill[Orchid] (-1.5,-0.5) rectangle ++(0.5,0.5); + \fill[Dandelion] (-1,-0.5) rectangle ++(0.5,0.5); + \fill[LimeGreen] (-0.5,-0.5) rectangle ++(1,0.5); + \fill[Salmon] (0.5,-0.5) rectangle ++(0.5,0.5); + \fill[Turquoise] (1,-0.5) rectangle ++(0.5,0.5); + + \draw[draw=black] (-1.5,-0.5) rectangle ++(3,0.5); + \draw[draw=black] (-1,-0.5) rectangle ++(2,0.5); + \draw[draw=black] (-0.5,-0.5) rectangle ++(1,0.5); + + \draw [thick,densely dotted, rounded corners=1mm](0,3.8) -- (0.1, 2.9) -- (-0.15, 2.7) -- (-0.1, 2.4); + + \draw [thick,densely dotted, rounded corners=1mm](-0.1, 2.1) -- (-0.1, 1.7) -- (0.15, 1.4) -- (0.1, 1.1); + + + \node[draw=none, fill=none] at (-1.25,-0.25) {$u$}; + \node[draw=none, fill=none] at (-0.75,-0.25) {$v$}; + \node[draw=none, fill=none] at (0,-0.25) {$w$}; + \node[draw=none, fill=none] at (0.75,-0.25) {$x$}; + \node[draw=none, fill=none] at (1.25,-0.25) {$y$}; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/cfl/pumping2.tex b/tex/figures/cfl/pumping2.tex new file mode 100644 index 0000000..e645f44 --- /dev/null +++ b/tex/figures/cfl/pumping2.tex @@ -0,0 +1,40 @@ +\begin{tikzpicture} + \node[draw=none, fill=none] at (0, 4) {S}; + \node[draw=none, fill=none] at (-0.1, 2.8) {A}; + \node[draw=none, fill=none] at (0.1, 1.6) {A}; + \node[draw=none, fill=none] at (-0, 0.8) {A}; + + \draw (-2,0) -- (0,3.8); + \draw (0,3.8) -- (2,0); + \draw (-1.5,0) -- (-0.1,2.6); + \draw (-0.1,2.6) -- (1.5,0); + \draw (-1,0) -- (0.1,1.4); + \draw (0.1,1.4) -- (1,0); + \draw (-0.5,0) -- (0,0.6); + \draw (0,0.6) -- (0.5,0); + + \fill[Orchid] (-2,-0.5) rectangle ++(0.5,0.5); + \fill[Dandelion] (-1.5,-0.5) rectangle ++(1,0.5); + \fill[LimeGreen] (-0.5,-0.5) rectangle ++(1,0.5); + \fill[Salmon] (0.5,-0.5) rectangle ++(1,0.5); + \fill[Turquoise] (1.5,-0.5) rectangle ++(0.5,0.5); + + \draw[draw=black] (-2,-0.5) rectangle ++(4,0.5); + \draw[draw=black] (-1.5,-0.5) rectangle ++(3,0.5); + \draw[draw=black] (-1,-0.5) rectangle ++(2,0.5); + \draw[draw=black] (-0.5,-0.5) rectangle ++(1,0.5); + + \draw [thick,densely dotted, rounded corners=1mm](0,3.8) -- (0.1, 3.4) -- (-0.15, 3.2) -- (-0.1, 2.9); + + \draw [thick,densely dotted, rounded corners=1mm](-0.1, 2.6) -- (-0.1, 2.3) -- (0.15, 1.9) -- (0.1, 1.75); + + \draw [thick,densely dotted, rounded corners=1mm](0.1,1.4) -- (-0.05, 1.1) -- (0, 1); + + \node[draw=none, fill=none] at (-1.75,-0.25) {$u$}; + \node[draw=none, fill=none] at (-1.25,-0.25) {$v$}; + \node[draw=none, fill=none] at (-0.75,-0.25) {$v$}; + \node[draw=none, fill=none] at (0,-0.25) {$w$}; + \node[draw=none, fill=none] at (0.75,-0.25) {$x$}; + \node[draw=none, fill=none] at (1.25,-0.25) {$x$}; + \node[draw=none, fill=none] at (1.75,-0.25) {$y$}; + \end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/cfl/tree0.tex b/tex/figures/cfl/tree0.tex new file mode 100644 index 0000000..e32f10e --- /dev/null +++ b/tex/figures/cfl/tree0.tex @@ -0,0 +1,27 @@ +\begin{tikzpicture}[sibling distance=4em, + every node/.style = {shape=rectangle, rounded corners, + draw, align=center}]] + \node {S} + child { node {a} } + child { node {S} + child { node {$\varepsilon$}} + } + child { node {b} } + child { node {S} + child {node {a}} + child { node {S} + child { node {$\varepsilon$}} + } + child { node {b} } + child { node {S} + child {node {a}} + child {node {S} + child {node {$\varepsilon$}} + } + child {node {b}} + child {node {S} + child {node {$\varepsilon$}} + } + } + }; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/main.tex b/tex/main.tex index c2ee782..5772ee8 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -49,6 +49,7 @@ \input{GraphTheoryIntro} \input{FormalLanguageTheoryIntro} \input{RegularLanguages} +\input{Context-Free_Languages} \backmatter \setchapterstyle{plain} diff --git a/tex/styles/math.tex b/tex/styles/math.tex index 0610eb4..5a60756 100644 --- a/tex/styles/math.tex +++ b/tex/styles/math.tex @@ -2,3 +2,4 @@ \usepackage{nicematrix} % \setmathfont[range={\doubleplus}, Scale=MatchLowercase]{Asana Math} +\NewDocumentCommand{\derives}{O{*}}{\xRightarrow[]{#1}} diff --git a/tex/styles/theorems.tex b/tex/styles/theorems.tex index 90cea4e..c7eccf6 100644 --- a/tex/styles/theorems.tex +++ b/tex/styles/theorems.tex @@ -61,8 +61,8 @@ \declaretheorem[name=Пример, numberwithin=chapter, style=myStyle]{example} \declaretheorem[name=Замечание, numbered=no, style=myStyle]{remark} -% \declaretheorem[name=Доказательство, numbered=no, style=myProofStyleWithFrame]{proofReplace} -% \renewenvironment{proof}[1][\proofname]{\begin{proofReplace}}{\end{proofReplace}} +\declaretheorem[name=Доказательство, numbered=no, style=myProofStyleWithFrame]{proofReplace} +\renewenvironment{proof}[1][\proofname]{\begin{proofReplace}}{\end{proofReplace}} % \declaretheorem[name=Доказательство, numbered=no, style=myProofStyleWithFrame]{longProof} \declaretheorem[name={Набросок доказательства}, numbered=no, style=myProofStyleWithFrame]{proofSketch} diff --git a/tex/styles/utils.tex b/tex/styles/utils.tex index 2d88773..e633c9d 100644 --- a/tex/styles/utils.tex +++ b/tex/styles/utils.tex @@ -1,5 +1,6 @@ \usepackage{xurl} % Разрешить переносить URL на любой букве \usepackage[noheader]{gitver} +\usepackage{subcaption} \NewDocumentCommand{\email}{m}{\href{mailto:#1}{#1}} % Кликабельный email From c72abd28697225561d6af3832703004581b670c4 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Wed, 19 Jun 2024 21:09:02 +0300 Subject: [PATCH 22/29] Restore all chapters to tree --- tex/CFPQ_to_Datalog.tex | 142 ++ tex/CYK_for_CFPQ.tex | 732 +++++++++ tex/CombinatorsForCFPQ.tex | 28 + tex/Conclusion.tex | 7 + tex/ConjunctiveAndBooleanLanguages.tex | 235 +++ tex/DerivativesForCFPQ.tex | 156 ++ tex/FLPQ.tex | 146 ++ tex/GLL-based_CFPQ.tex | 647 ++++++++ tex/GLR-based_CFPQ.tex | 1159 ++++++++++++++ tex/Matrix-based_CFPQ.tex | 367 +++++ ...ple_Context-Free_Language_Reachability.tex | 401 +++++ tex/Multiple_Context-Free_Languages.tex | 207 +++ tex/RPQ.tex | 669 ++++++++ tex/SPPF.tex | 717 +++++++++ tex/TensorProduct.tex | 1366 +++++++++++++++++ tex/figures/GLR/CLR_example.tex | 99 ++ tex/figures/GLR/GLR_example.tex | 101 ++ tex/figures/GLR/LL_LR.tex | 21 + tex/figures/GLR/LR0/complete.tex | 67 + tex/figures/GLR/LR0/state0.tex | 14 + tex/figures/GLR/LR0/state1.tex | 23 + tex/figures/GLR/LR0/state2.tex | 29 + tex/figures/GLR/LR0/state3.tex | 42 + tex/figures/GLR/LR0/state4.tex | 48 + tex/figures/GLR/LR0/state5.tex | 62 + tex/figures/cyk/graph1.tex | 19 + tex/figures/flpq/path1.tex | 8 + tex/figures/flpq/path2.tex | 12 + tex/figures/gll/complete.tex | 26 + tex/figures/gll/state0.tex | 3 + tex/figures/gll/state1.tex | 8 + tex/figures/gll/state2.tex | 10 + tex/figures/gll/state3.tex | 13 + tex/figures/gll/state4.tex | 15 + tex/figures/gll/state5.tex | 17 + tex/figures/gll/state6.tex | 19 + tex/figures/gll/state7.tex | 22 + tex/figures/gll/state8.tex | 24 + tex/figures/mcfg/mcfg.pdf | Bin 0 -> 6679 bytes tex/figures/mcfg/mcfg.svg | 164 ++ tex/figures/mcfg/mcfg_2.pdf | Bin 0 -> 6053 bytes tex/figures/mcfg/mcfg_2.svg | 157 ++ tex/figures/multi/graph0.tex | 18 + tex/figures/tensor/graph0.tex | 20 + tex/figures/tensor/graph1.tex | 21 + tex/figures/tensor/graph2.tex | 21 + tex/figures/tensor/graph3.tex | 21 + tex/figures/tensor/graph4.tex | 22 + tex/figures/tensor/graph5.tex | 23 + tex/figures/tensor/recursive.tex | 16 + tex/main.tex | 16 + ...ageConstrainedReachabilityLectureNotes.tex | 204 +++ 52 files changed, 8384 insertions(+) create mode 100644 tex/CFPQ_to_Datalog.tex create mode 100644 tex/CYK_for_CFPQ.tex create mode 100644 tex/CombinatorsForCFPQ.tex create mode 100644 tex/Conclusion.tex create mode 100644 tex/ConjunctiveAndBooleanLanguages.tex create mode 100644 tex/DerivativesForCFPQ.tex create mode 100644 tex/FLPQ.tex create mode 100644 tex/GLL-based_CFPQ.tex create mode 100644 tex/GLR-based_CFPQ.tex create mode 100644 tex/Matrix-based_CFPQ.tex create mode 100644 tex/Multiple_Context-Free_Language_Reachability.tex create mode 100644 tex/Multiple_Context-Free_Languages.tex create mode 100644 tex/RPQ.tex create mode 100644 tex/SPPF.tex create mode 100644 tex/TensorProduct.tex create mode 100644 tex/figures/GLR/CLR_example.tex create mode 100644 tex/figures/GLR/GLR_example.tex create mode 100644 tex/figures/GLR/LL_LR.tex create mode 100644 tex/figures/GLR/LR0/complete.tex create mode 100644 tex/figures/GLR/LR0/state0.tex create mode 100644 tex/figures/GLR/LR0/state1.tex create mode 100644 tex/figures/GLR/LR0/state2.tex create mode 100644 tex/figures/GLR/LR0/state3.tex create mode 100644 tex/figures/GLR/LR0/state4.tex create mode 100644 tex/figures/GLR/LR0/state5.tex create mode 100644 tex/figures/cyk/graph1.tex create mode 100644 tex/figures/flpq/path1.tex create mode 100644 tex/figures/flpq/path2.tex create mode 100644 tex/figures/gll/complete.tex create mode 100644 tex/figures/gll/state0.tex create mode 100644 tex/figures/gll/state1.tex create mode 100644 tex/figures/gll/state2.tex create mode 100644 tex/figures/gll/state3.tex create mode 100644 tex/figures/gll/state4.tex create mode 100644 tex/figures/gll/state5.tex create mode 100644 tex/figures/gll/state6.tex create mode 100644 tex/figures/gll/state7.tex create mode 100644 tex/figures/gll/state8.tex create mode 100644 tex/figures/mcfg/mcfg.pdf create mode 100644 tex/figures/mcfg/mcfg.svg create mode 100644 tex/figures/mcfg/mcfg_2.pdf create mode 100644 tex/figures/mcfg/mcfg_2.svg create mode 100644 tex/figures/multi/graph0.tex create mode 100644 tex/figures/tensor/graph0.tex create mode 100644 tex/figures/tensor/graph1.tex create mode 100644 tex/figures/tensor/graph2.tex create mode 100644 tex/figures/tensor/graph3.tex create mode 100644 tex/figures/tensor/graph4.tex create mode 100644 tex/figures/tensor/graph5.tex create mode 100644 tex/figures/tensor/recursive.tex create mode 100644 tex/old_FormalLanguageConstrainedReachabilityLectureNotes.tex diff --git a/tex/CFPQ_to_Datalog.tex b/tex/CFPQ_to_Datalog.tex new file mode 100644 index 0000000..c5c4c4a --- /dev/null +++ b/tex/CFPQ_to_Datalog.tex @@ -0,0 +1,142 @@ +\chapter{От CFPQ к вычислению Datalog-запросов}\label{Subsection Datalog} +Рассмотрим грамматику $S \rightarrow aSb \mid SS \mid \varepsilon$, заданную через набор предикатов: +\begin{itemize} + \item $a(i, w)$ --- Предикат, соответствующий терминалу. Обращается в True, если на $i$-том месте в строке $w$ стоит символ $a$ + \item $S(i, j, w)$ --- Предикат, соответствующий нетерминалу. Обращается в True, если выполняется одно из условий: + \begin{enumerate} + \item $i == j \quad(\varepsilon)$ + \item $\exists k: i \leq k \leq j \And S(i, k - 1, w) \And S(k, j, w) \quad (SS)$ + \item ${a(i, w) \And S(i+1, j-1, w) \And b(j-1, w)} \quad (aSb)$ + \end{enumerate} +\end{itemize} + +Таким образом $S(0,|w|,w)$ покажет, выводится ли строка $w$ из данной грамматики, +а $S(\_,\_,w)$ даст нам список всех цепочек внутри $w$, выводящихся из $S$. + +\subsection{Datalog} +Datalog~\cite{Datalog}\footnote{\url{https://www.computer.org/csdl/journal/tk/1989/01/k0146/13rRUx0xPIQ}} --- декларативный логический язык программирования. Используется для написания запросов к дедуктивным базам данных\footnote{\url{https://en.wikipedia.org/wiki/Deductive_database}}. + +\begin{example} + Пример программы на даталоге. + \begin{enumerate} + \item Набор фактов (часто факты находятся в базе данных): + \begin{itemize} + \item $a(0).$ + \item $b(1).$ + \item $a(2).$ + \item $b(3).$ + \item $s(I, I).$ + \end{itemize} + \item Набор правил: + \begin{itemize} + \item $s(I, J) \coloneq s(I, K-1), s(K,J), (I \leq K \leq J)$ + \item $s(I,J)\coloneq a(I), s(I+1, J-1),b(J)$ + \end{itemize} + \item Запросы: + \begin{itemize} + \item $?- s(I, J)$ + \end{itemize} + \end{enumerate} +\end{example} + +Таким образом мы описали на даталоге строку через набор фактов, грамматику, указанную выше, через набор фактов и правил и сделали запрос на все цепочки, выводящиеся из $S$. + +\textbf{NB!} Обратите внимание~\cite{Datalog}, что строки, начинающиеся с большой буквы, в даталоге считаются переменными. Также важно, что все переменные неявно квантифицированны. + + +\subsection{Datalog для работы с графами} +На даталоге также можно задавать графы и писать к ним запросы. +\begin{example} + Пример описания графа на даталоге. + \begin{center} + \begin{tikzpicture}[shorten >=1pt,on grid,auto] + \node[state] (q_0) {$0$}; + \node[state] (q_1) [above right=of q_0] {$1$}; + \node[state] (q_2) [right=of q_0] {$2$}; + \node[state] (q_3) [right=of q_2] {$3$}; + \path[->] + (q_0) edge node {$a$} (q_1) + (q_1) edge node {$a$} (q_2) + (q_2) edge node {$a$} (q_0) + (q_2) edge[bend left, above] node {$b$} (q_3) + (q_3) edge[bend left, below] node {$b$} (q_2); + \end{tikzpicture} + \end{center} +\begin{itemize} + \item[] $a(0, 1).$ + \item[] $a(1, 2).$ + \item[] $a(2, 0).$ + \item[] $b(2, 3).$ + \item[] $b(3, 2).$ +\end{itemize} + +\end{example} + +Теперь зададим рассмотренную выше грамматику для работы с графом. +\begin{itemize} + \item[] $s(I, I).$ + \item[] $s(I,J) \coloneq s(I, K-1),s(K, J).$ + \item[] $s(I, J) \coloneq a(I, L),S(L,M),b(M,J).$ +\end{itemize} + +Тогда запрос $?-s(I, J)$ выдаст нам все такие пути в графе, что последовательность составляющих их вершин в порядке прохождения выводится их грамматики. + +\subsection{Алгоритм Эрли} +Для распознавания контекстно-свободных грамматик может использоваться алгоритм Эрли~\cite{Earley} \footnote{\url{https://en.wikipedia.org/wiki/Earley}}. +Рассмотрим грамматику $G=(N,T,P,S)$, слово $a_1...a_n$, +и правило $A \rightarrow \alpha\beta$. Будем считать, что утверждение +$[A\rightarrow \alpha \bullet \beta](i,j), j \in [1..n]$ является истиной, если верно, что: +\begin{itemize} + \item $\alpha \xrightarrow{\smash{*}} a_{i+1}...a_j$ (Последовательность выводится из $\alpha$) + \item $S \xrightarrow{\smash{*}} a_1...a_jA_\gamma$ +\end{itemize} + + +Рассмотрим правила вывода для подобных утверждений: + +\begin{enumerate} + \item $\frac{S \rightarrow \alpha \in P}{[S \rightarrow \bullet \alpha](0,0)}$ Инициализация (Init) + + \item $\frac{\left[A \rightarrow \alpha \bullet a_{j+1} \beta\right](i, j)}{\left[A \rightarrow \alpha a_{j+1} \bullet \beta\right](i, j+1)}$ Сканирование (Scan) + + \item $\frac{[A \rightarrow \alpha \cdot B \beta](i, j) \quad B \rightarrow \gamma \in P}{[B \rightarrow \bullet \gamma](j, j)}$ Предсказание (Predict) + + \item $\frac{[A \rightarrow \alpha \cdot B](i, j) \quad[B \rightarrow \gamma \bullet](j, k)}{[A \rightarrow \alpha B \bullet \beta](i, k)}$ Завершение (Complete) + +\end{enumerate} + +Идея алгоритма Эрли заключается в том, чтобы, начиная с инициализации, используя правила, вывести утверждение, содержащие данную строку слева от точки, и ничего справа, или попробовать все возможные выводы и признать, что строка не выводима. + +Сложность алгоритма Эрли составляет $O(|P|^2n^3)$ + +\begin{example} Пример начала одной из веток дерева вывода для алгоритма Эрли для рассматриваемой грамматики + + $$\underline{S \rightarrow SS} \quad Init$$ + $$\underline{[S \rightarrow \bullet SS](0,0), \space S \rightarrow aSb} \quad Predict$$ + $$\underline{[S \rightarrow \bullet aSb](0,0)} \quad Scan$$ + $$\underline{[S \rightarrow a \bullet Sb](0,1), S \rightarrow \varepsilon} \quad Predict$$ + $$\underline{[S \rightarrow \bullet](0, 1), [S \rightarrow aS \bullet b](0,1)} \quad Complete$$ + $$\underline{[S \rightarrow aS \bullet b](0,1)} \quad Scan$$ + $$\underline{[S \rightarrow \bullet SS](0,0),[S \rightarrow aSb \bullet](0,2)} \quad Complete$$ + $$[\underline{S \rightarrow S \bullet S](0,2)}$$ + $$\cdot\cdot\cdot$$ + +\end{example} + +Сложность можно понизить, изменив правила ``Предсказание'' и ``Завершение'' таким образом: +\begin{itemize} + \item $\frac{[A \rightarrow \alpha \cdot B \beta](i, j) \quad B \rightarrow \gamma \in P}{[B \rightarrow \bullet \gamma](j, j)} \Rightarrow$ $ + \frac{[A \rightarrow \alpha \cdot B \beta](i, j)}{? B(j)}; \quad \frac{? B(j) \quad B \rightarrow \gamma \in P}{[B \rightarrow \cdot \gamma](j, j)}$ + \item $\frac{[A \rightarrow \alpha \cdot B](i, j) \quad[B \rightarrow \gamma \bullet](j, k)}{[A \rightarrow \alpha B \bullet \beta](i, k)} \Rightarrow$ $\frac{[B \rightarrow \gamma \bullet](j, k)}{B(j, k)}; \quad \frac{[A \rightarrow \alpha \cdot B \beta](i, j) \quad B(j, k)}{[A \rightarrow \alpha B \cdot \beta](i, k)}$ +\end{itemize} +Так, разложив каждое правило на два, мы избавляемся от необходимости перевычислять дерево разбора каждого нетерминала после того, как однократно вычислим, что он выводим (мемоизируем его). Получаем сложность $O(|P|)$. + +Описанный подход мемоизации~\cite{Magic} части используется для оптимизации программ на даталоге. Можно либо видоизменять правила, задающие грамматику в тексте программы, либо модифицировать компилятор, чтобы он пытался сделать это автоматически. +\section{Вопросы и задачи} +\begin{enumerate} + \item Написать синтаксический анализатор раз. + \item Написать синтаксический анализатор два. + \item Побаловаться с неоднозначными грамматиками + \item Побаловаться с конъюнктивными грамматиками. + \item Графы? +\end{enumerate} \ No newline at end of file diff --git a/tex/CYK_for_CFPQ.tex b/tex/CYK_for_CFPQ.tex new file mode 100644 index 0000000..a4da827 --- /dev/null +++ b/tex/CYK_for_CFPQ.tex @@ -0,0 +1,732 @@ +\chapter{CYK для вычисления КС запросов}\label{chpt:CFPQ_CYK} + +В данной главе мы рассмотрим алгоритм CYK, позволяющий установить принадлежность слова грамматике и предоставить его вывод, если таковой имеется. + +Наш главный интерес заключается в возможности применения данного алгоритма для решения описанной в предыдущей главе задачи --- поиска путей с ограничениями в терминах формальных языков. Как уже было указано выше, будем рассматривать случай контекстно-свободных языков. + +\section{Алгоритм CYK}\label{sect:lin_CYK} + +Алгоритм CYK (Cocke-Younger-Kasami) --- один из классических алгоритмов синтаксического анализа. Его асимптотическая сложность в худшем случае --- $O(n^3 * |N|)$, где $n$ --- длина входной строки, а $N$ --- количество нетерминалов во входной грамматике~\cite{Hopcroft+Ullman/79/Introduction}. + +Для его применения необходимо, чтобы подаваемая на вход грамматика находилась в Нормальной Форме Хомского (НФХ)~\ref{section:CNF}. Других ограничений нет и, следовательно, данный алгоритм применим для работы с произвольными контекстно-своболными языками. + +В основе алгоритма лежит принцип динамического программирования. Используются два соображения: + +\begin{enumerate} +\item Из нетерминала $A$ выводится цепочка $\omega$ при помощи правила $A \to a$ тогда и только тогда, когда $a= \omega$: +\[ + A \derives \omega \iff \omega = a +\] + +\item Из нетерминала $A$ выводится цепочка $\omega$ при помощи правила $A \to B C$ тогда и только тогда, когда существуют две цепочки $\omega_1$ и $\omega_2$ такие, что $\omega_1$ выводима из $B$, $\omega_2$ выводима из $C$ и при этом $\omega = \omega_1 \omega_2$: +\[ +A \derives[] B C \derives \omega \iff \exists \omega_1, \omega_2 : \omega = \omega_1 \omega_2, B \derives \omega_1, C \derives \omega_2 +\] + +Переформулируем эти утверждения в терминах позиций в строке: +\[ +A \derives[] B C \derives \omega \iff \exists k \in [1 \dots |\omega|] : B \derives \omega[1 \dots k], C \derives \omega[k+1 \dots |\omega|] +\] +\end{enumerate} + +В процессе работы алгоритма заполняется булева трехмерная матрица $M$ размера $n \times n \times |N|$ таким образом, что +\[M[i, j, A] = true \iff A \derives \omega[i \dots j]\]. + +Первым шагом инициализируем матрицу, заполнив значения $M[i, i, A]$: + +\begin{itemize} + \item $M[i, i, A] = true \text{, если в грамматике есть правило } A \to \omega[i]$. + \item $M[i, i, A] = false$, иначе. +\end{itemize} + +Далее используем динамику: на шаге $m > 1$ предполагаем, что ячейки матрицы $M[i', j', A]$ заполнены для всех нетерминалов $A$ и пар $i', j': j' - i' < m$. +Тогда можно заполнить ячейки матрицы $M[i, j, A] \text{, где } j - i = m$ следующим образом: +\[ M[i, j, A] = \bigvee_{A \to B C}^{}{\bigvee_{k=i}^{j-1}{M[i, k, B] \wedge M[k, j, C]}} \] + +По итогу работы алгоритма значение в ячейке $M[0, |\omega|, S]$, где $S$ --- стартовый нетерминал грамматики, отвечает на вопрос о выводимости цепочки $\omega$ в грамматике. + +\begin{example}\label{exampl:CYK} + Рассмотрим пример работы алгоритма CYK на грамматике правильных скобочных последовательностей в Нормальной Форме Хомского. + + +\begin{align*} +S &\to A S_2 \mid \varepsilon & S_2 &\to b \mid B S_1 \mid S_1 S_3 & A &\to a \\ +S_1 &\to A S_2 & S_3 &\to b \mid B S_1 & B &\to b\\ +\end{align*} + +Проверим выводимость цепочки $\omega = a a b b a b$. + +Так как трехмерные матрицы рисовать на двумерной бумаге не очень удобно, мы будем иллюстрировать работу алгоритма двумерными матрицами размера $n \times n$, где в ячейках указано множество нетерминалов, выводящих соответствующую подстроку. + +Шаг 1. Инициализируем матрицу элементами на главной диагонали: + +\[ +\begin{pmatrix} +\{A\} & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ +\varnothing & \{A\} & \varnothing & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \varnothing \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ +\end{pmatrix} +\] + +Шаг 2. Заполняем диагональ, находящуюся над главной: + +\[ +\begin{pmatrix} +\{A\} & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ +\varnothing & \{A\} & \cellcolor{lightgray}\{S_1\} & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \cellcolor{lightgray}\{S_1\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ +\end{pmatrix} +\] + +В двух ячейках появилисб нетерминалы $S_1$ благодяря присутствиб в грамматике правила $S_1 \to A S_2$. + +Шаг 3. Заполняем следующую диагональ: + +\[ +\begin{pmatrix} +\{A\} & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ +\varnothing & \{A\} & \{S_1\} & \cellcolor{lightgray}\{S_2\} & \varnothing & \varnothing \\ +\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \cellcolor{lightgray}\{S_2, S_3\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \{S_1\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ +\end{pmatrix} +\] + +Шаг 4. И следующую за ней: + +\[ +\begin{pmatrix} +\{A\} & \varnothing & \varnothing & \cellcolor{lightgray}\{S_1, S\} & \varnothing & \varnothing \\ +\varnothing & \{A\} & \{S_1\} & \{S_2\} & \varnothing & \varnothing \\ +\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \{S_2, S_3\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \{S_1\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ +\end{pmatrix} +\] + +Шаг 5 Заполняем предпоследнюю диагональ: + +\[ +\begin{pmatrix} +\{A\} & \varnothing & \varnothing & \{S_1, S\} & \varnothing & \varnothing \\ +\varnothing & \{A\} & \{S_1\} & \{S_2\} & \varnothing & \cellcolor{lightgray}\{S_2\} \\ +\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \{S_2, S_3\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \{S_1\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ +\end{pmatrix} +\] + +\bigbreak +Шаг 6. Завершаем выполнение алгоритма: + +\[ +\begin{pmatrix} +\{A\} & \varnothing & \varnothing & \{S_1, S\} & \varnothing & \cellcolor{lightgray}\{S_1, S\} \\ +\varnothing & \{A\} & \{S_1\} & \{S_2\} & \varnothing & \{S_2\} \\ +\varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \{S_2, S_3\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \{S_1\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ +\end{pmatrix} +\] + + +Стартовый нетерминал находится в верхней правой ячейке, а значит цепочка $a a b b a b$ выводима в нашей грамматике. +\end{example} + +\begin{example} +Теперь выполним алгоритм на цепочке $\omega=abaa$. + +Шаг 1. Инициализируем таблицу: + +\[ +\begin{pmatrix} +\{A\} & \varnothing & \varnothing & \varnothing \\ +\varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing \\ +\varnothing & \varnothing & \{A\} & \varnothing \\ +\varnothing & \varnothing & \varnothing & \{A\} \\ +\end{pmatrix} +\] + +Шаг 2. Заполняем следующую диагональ: + +\[ +\begin{pmatrix} +\{A\} & \cellcolor{lightgray}\{S_1, S\} & \varnothing & \varnothing \\ +\varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing \\ +\varnothing & \varnothing & \{A\} & \varnothing \\ +\varnothing & \varnothing & \varnothing & \{A\} \\ +\end{pmatrix} +\] + +Больше ни одну ячейку в таблице заполнить нельзя и при этом стартовый нетерминал отсутствует в правой верхней ячейке, а значит эта строка не выводится в грамматике правильных скобочных последовательностей. + +\end{example} + +\section{Алгоритм для графов на основе CYK} +\label{graph:CYK} +Первым шагом на пути к решению задачи достижимости с использованием CYK является модификация представления входа. Прежде мы сопоставляли каждому символу слова его позицию во входной цепочке, поэтому при инициализации заполняли главную диагональ матрицы. Теперь вместо этого обозначим числами позиции между символами. В результате слово можно представить в виде линейного графа следующим образом(в качестве примера рассмотрим слово $a a b b a b$ из предыдущей главы~\ref{sect:lin_CYK}): + +\begin{center} + \begin{tikzpicture}[shorten >=1pt,on grid,auto] + \node[state] (q_0) at (0,0) {$0$}; + \node[state] (q_1) at (2,0) {$1$}; + \node[state] (q_2) at (4,0) {$2$}; + \node[state] (q_3) at (6,0) {$3$}; + \node[state] (q_4) at (8,0) {$4$}; + \node[state] (q_5) at (10,0) {$5$}; + \node[state] (q_6) at (12,0) {$6$}; + \path[->] + (q_0) edge node {$a$} (q_1) + (q_1) edge node {$a$} (q_2) + (q_2) edge node {$b$} (q_3) + (q_3) edge node {$b$} (q_4) + (q_4) edge node {$a$} (q_5) + (q_5) edge node {$b$} (q_6); + \end{tikzpicture} +\end{center} + +Что нужно изменить в описании алгоритма, чтобы он продолжал работать при подобной нумерации? Каждая буква теперь идентифицируется не одним числом, а парой --- номера слева и справа от нее. При этом чисел стало на одно больше, чем при прежнем способе нумерации. + +Возьмем матрицу $(n + 1) \times (n + 1) \times |N|$ и при инициализации будем заполнять не главную диагональ, а диагональ прямо над ней. Таким образом, мы начинаем наш алгоритм с определения значений $M[i, j, A] \text{, где } j = i + 1$. При этом наши дальнейшие действия в рамках алгоритма не изменятся. + +Для примера~\ref{exampl:CYK} на шаге инициализации матрица выглядит следующим образом: + +\[ +\begin{pmatrix} +\varnothing & \{A\} & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \{A\} & \varnothing & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \varnothing \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ + +\end{pmatrix} +\] + +А в результате работы алгоритма имеем: + +\[ +\begin{pmatrix} +\varnothing & \{A\} & \varnothing & \varnothing & \{S_1, S\} & \varnothing & \{S_1, S\} \\ +\varnothing & \varnothing & \{A\} & \{S_1\} & \{S_2\} & \varnothing & \{S_2\} \\ +\varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \varnothing & \varnothing \\ +\varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} & \varnothing & \{S_2, S_3\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{A\} & \{S_1\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \{B, S_2, S_3\} \\ +\varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} +\] + +Мы представили входную строку в виде линейного графа, а на шаге инициализации получили его матрицу смежности. Добавление нового нетерминала в язейку матрицы можно рассматривать как нахождение нового пути между соответствующими вершинами, выводимого из добавленного нетерминала. Таким образом, шаги алгоритма напоминают построение транзитивного замыкания графа. Различие заключается в том, что мы добавляем новые ребра только для тех пар нетерминалов, для которых существует соответстующее правило в грамматике. + +Алгоритм можно обобщить и на произвольные графы с метками, рассматриваемые в этом курсе. При этом можно ослабить ограничение на форму входной грамматики: она должна находиться в ослабленной Нормальной Форме Хомского~(\ref{defn:wCNF}). + +Шаг инициализации в алгоритме теперь состоит из двух пунктов. +\begin{itemize} +\item Как и раньше, с помощью продукций вида \[A \to a \text{, где } A \in N, a \in \Sigma\] +заменяем терминалы на ребрах входного графа на множества нетерминалов, из которых они выводятся. +\item Добавляем в каждую вершину петлю, помеченную множеством нетерминалов для которых в данной грамматике есть правила вида $$A \to \varepsilon\text{, где } A \in N.$$ +\end{itemize} + + Затем используем матрицу смежности получившегося графа (обозначим ее $M$) в качестве начального значения. Дальнейший ход алгоритма можно описать псевдокодом, представленным в листинге~\ref{alg:graphParseCYK}. + +\begin{algorithm}[H] + \begin{algorithmic}[1] + \caption{Алгоритм КС достижимости на основе CYK} + \label{alg:graphParseCYK} + \Function{contextFreePathQuerying}{G, $\mathcal{G}$} + + \State{$n \gets$ the number of nodes in $\mathcal{G}$} + \State{$M \gets$ the modified adjacency matrix of $\mathcal{G}$} + \State{$P \gets$ the set of production rules in $G$} + \While{$M$ is changing} + \For {$k \in 0..n$} + \For {$i \in 0..n$} + \For {$j \in 0..n$} + \ForAll {$N_1 \in M[i, k]$, $N_2 \in M[k, j]$} + \If {$N_3 \to N_1 N_2 \in P$ } + \State{$M[i, j] \mathrel{+}= \{N_3\}$} + \EndIf + \EndFor + \EndFor + \EndFor + \EndFor + \EndWhile + \State \Return $M$ + \EndFunction + \end{algorithmic} +\end{algorithm} + +После завершения алгоритма, если в некоторой ячейке результируюшей матрицы с номером $(i, j)$ находятся стартовый нетерминал, то это означает, что существует путь из вершины $i$ в вершину $j$, удовлетворяющий данной грамматике. Таким образом, полученная матрица является ответом для задачи достижимости для заданных графа и грамматики. + +\begin{example} +\label{CYK_algorithm_ex} +Рассмотрим работу алгоритма на графе + +\begin{center} + \input{figures/graph/graph0.tex} +\end{center} + +и грамматике: + +\begin{align*} +S & \to A B & A & \to a \\ +S & \to A S_1 & B & \to b\\ +S_1 & \to S B &&\\ +\end{align*} + +Данный пример является классическим и еще не раз будет использоваться в рамках данного курса. \\ + +\textbf{Инициализация.} +Заменяем терминалы на ребрах графа на нетерминалы, из которых они выводятся, и строим матрицу смежности получившегося графа: + +\begin{center} + \input{figures/cyk/graph1.tex} +\end{center} + +\[ +\begin{pmatrix} +\varnothing & \{A\} & \varnothing & \varnothing \\ +\varnothing & \varnothing & \{A\} & \varnothing \\ +\{A\} & \varnothing & \varnothing & \{B\} \\ +\varnothing & \varnothing & \{B\} & \varnothing \\ +\end{pmatrix} +\] + +\textbf{Итерация 1.} +Итерируемся по $k$, $i$ и $j$, пытаясь найти пары нетерминалов, для которых существуют правила вывода, их выводящие. Нам интересны следующие случаи: + +\begin{itemize} + \item $k = 2, i = 1, j = 3: A \in M[1, 2], B \in M[2, 3]$, так как в грамматике присутствует правило $S \to A B$, добавляем нетерминал $S$ в ячейку $M[1, 3]$. + \item $k = 3, i = 1, j = 2: S \in M[1, 3], B \in M[3, 2]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[1, 2]$. +\end{itemize} + +В остальных случаях либо какая-то из клеток пуста, либо не существует продукции в грамматике, выводящей данные два нетерминала. + +Матрица после данной итерации: + +\[ +\begin{pmatrix} +\varnothing & \{A\} & \varnothing & \varnothing \\ +\varnothing & \varnothing & \cellcolor{lightgray}\{A, \boldsymbol{S_1}\} & \cellcolor{lightgray}\{S\} \\ +\{A\} & \varnothing & \varnothing & \{B\} \\ +\varnothing & \varnothing & \{B\} & \varnothing \\ +\end{pmatrix} +\] + +\textbf{Итерация 2.} +Снова итерируемся по $k$, $i$, $j$. Рассмотрим случаи: + +\begin{itemize} + \setlength\itemsep{1em} + \item $k = 1, i = 0, j = 2: A \in M[0, 1], S_1 \in M[1, 2]$, так как в грамматике присутствует правило $S \to A S_1$, добавляем нетерминал $S$ в ячейку $M[0, 2]$. + \item $k = 2, i = 0, j = 3: S \in M[0, 2], B \in M[2, 3]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[0, 3]$. +\end{itemize} + +Матрица на данном шаге: + +\[ +\begin{pmatrix} +\varnothing & \{A\} & \cellcolor{lightgray}\{S\} & \cellcolor{lightgray}\{S_1\} \\ +\varnothing & \varnothing & \{A, S_1\} & \{S\} \\ +\{A\} & \varnothing & \varnothing & \{B\} \\ +\varnothing & \varnothing & \{B\} & \varnothing \\ +\end{pmatrix} +\] + +\textbf{Итерация 3.} +Рассматриваемые на данном шаге случаи: + +\begin{itemize} + \setlength\itemsep{1em} + \item $k = 0, i = 2, j = 3: A \in M[2, 0], S_1 \in M[0, 3]$, так как в грамматике присутствует правило $S \to A S_1$, добавляем нетерминал $S$ в ячейку $M[2, 3]$. + \item $k = 3, i = 2, j = 2: S \in M[2, 3], B \in M[3, 2]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[2, 2]$. +\end{itemize} + +Матрица после этой итерации: + +\[ +\begin{pmatrix} +\varnothing & \{A\} & \{S\} & \{S_1\} \\ +\varnothing & \varnothing & \{A, S_1\} & \{S\} \\ +\{A\} & \varnothing & \cellcolor{lightgray}\{S_1\} & \cellcolor{lightgray}\{B, \boldsymbol{S}\} \\ +\varnothing & \varnothing & \{B\} & \varnothing \\ +\end{pmatrix} +\] + +\textbf{Итерация 4.} +Рассмариваемые случаи: + +\begin{itemize} + \setlength\itemsep{1em} + \item $k = 2, i = 1, j = 2: A \in M[1, 2], S_1 \in M[2, 2]$, так как в грамматике присутствует правило $S \to A S_1$, добавляем нетерминал $S$ в ячейку $M[1, 2]$. + \item $k = 2, i = 1, j = 3: S \in M[1, 2], B \in M[2, 3]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[1, 3]$. +\end{itemize} + +Матрица: + +\[ +\begin{pmatrix} +\varnothing & \{A\} & \{S\} & \{S_1\} \\ +\varnothing & \varnothing & \cellcolor{lightgray}\{A, \boldsymbol{S}, S_1\} & \cellcolor{lightgray}\{S, \boldsymbol{S_1}\} \\ +\{A\} & \varnothing & \{S_1\} & \{B, S\} \\ +\varnothing & \varnothing & \{B\} & \varnothing \\ +\end{pmatrix} +\] + +\textbf{Итерация 5.} +Рассмотрим на это шаге: + +\begin{itemize} + \setlength\itemsep{1em} + \item $k = 1, i = 0, j = 3: A \in M[0, 1], S_1 \in M[1, 3]$, поскольку в грамматике есть правило $S \to A S_1$, добавляем нетерминал $S$ в ячейку $M[0, 3]$. + \item $k = 3, i = 0, j = 2: S \in M[0, 3], B \in M[3, 2]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[0, 2]$. +\end{itemize} + +Матрица на этой итерации: +\[ +\begin{pmatrix} +\varnothing & \{A\} & \cellcolor{lightgray}\{S, \boldsymbol{S_1}\} & \cellcolor{lightgray}\{\boldsymbol{S}, S_1\} \\ +\varnothing & \varnothing & \{A, S, S_1\} & \{S, S_1\} \\ +\{A\} & \varnothing & \{S_1\} & \{B, S\} \\ +\varnothing & \varnothing & \{B\} & \varnothing \\ +\end{pmatrix} +\] + +\textbf{Итерация 6.} +Интересующие нас на этом шаге случаи: + +\begin{itemize} + \setlength\itemsep{1em} + \item $k = 0, i = 2, j = 2: A \in M[2, 0], S_1 \in M[0, 2]$, поскольку в грамматике есть правило $S \to A S_1$, добавляем нетерминал $S$ в ячейку $M[2, 2]$. + \item $k = 2, i = 2, j = 3: S \in M[2, 2], B \in M[2, 3]$, поскольку в грамматике есть правило $S_1 \to S B$, добавляем нетерминал $S_1$ в ячейку $M[2, 3]$. +\end{itemize} + +Матрица после данного шага: + +\[ +\begin{pmatrix} +\varnothing & \{A\} & \{S, S_1\} & \{S, S_1\} \\ +\varnothing & \varnothing & \{A, S, S_1\} & \{S, S_1\} \\ +\{A\} & \varnothing & \cellcolor{lightgray}\{\boldsymbol{S}, S_1\} & \cellcolor{lightgray}\{B, S, \boldsymbol{S_1}\} \\ +\varnothing & \varnothing & \{B\} & \varnothing \\ +\end{pmatrix} +\] + +На следующей итерации матрица не изменяется, поэтому заканчиваем работу алгоритма. В результате, если ячейка $M[i, j]$ содержит стартовый нетерминал $S$, то существует путь из $i$ в $j$, удовлетворяющий ограничениям, заданным грамматикой. +\end{example} + +Можно заметить, что мы делаем много лишних итераций. +Можно переписать алгоритм так, чтобы он не просматривал заведомо пустые ячейки. +Данную модификацию предложил Й.Хеллингс в работе~\cite{hellingsRelational}, также она реализована в работе~\cite{10.1007/978-3-319-46523-4_38}. + +Псевдокод алгоритма Хеллингса представлен в листинге~\ref{alg:graphParseHellings}. + +\begin{algorithm}[H] + \begin{algorithmic}[1] + \caption{Алгоритм Хеллингса} + \label{alg:graphParseHellings} + \Function{contextFreePathQuerying}{$G= \langle \Sigma, N, P, S \rangle$, $\mathcal{G} = \langle V,E,L \rangle$} + + \State{$r \gets \{(N_i,v,v) \mid v \in V \wedge N_i \to \varepsilon \in P \} \cup \{(N_i,v,u) \mid (v,t,u) \in E \wedge N_i \to t \in P \}$} + \State{$m \gets r$} + \While{$m \neq \varnothing$} + \State{$(N_i,v,u) \gets$ m.pick()} + \For {$(N_j,v',v) \in r$} + \For {$N_k \to N_j N_i \in P$ таких что $((N_k, v',u) \notin r)$} + \State{$m \gets m \cup \{(N_k, v',u)\}$} + \State{$r \gets r \cup \{(N_k, v',u)\}$} + \EndFor + \EndFor + \For {$(N_j,u,v') \in r$} + \For {$N_k \to N_i N_j \in P$ таких что $((N_k, v, v') \notin r)$} + \State{$m \gets m \cup \{(N_k, v, v')\}$} + \State{$r \gets r \cup \{(N_k, v, v')\}$} + \EndFor + \EndFor + + \EndWhile + \State \Return $r$ + \EndFunction + \end{algorithmic} +\end{algorithm} + + +\begin{example} + Запустим алгоритм Хеллингса на нашем примере. + + \textbf{Инициализация} + $$ + m = r = \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2)\} + $$ + + \textbf{Итерации внешнего цикла.} Будем считеть, что $r$ и $m$ --- упорядоченные списки и $pick$ возвращает его голову, оставляя хвост. + Новые элементы добавляются в конец. + \begin{enumerate} + \item Обрабатываем $(A,0,1)$. + Ни один из вложенных циклов не найдёт новых путей, так как для рассматриваемого ребра есть только две возможности достроить путь: $2 \xrightarrow{A} 0 \xrightarrow{A} 1$ и $0 \xrightarrow{A} 1 \xrightarrow{A} 2$ + и ни одна из соответствующих строк не выводтся в заданной грамматике. + \item Перед началом итерации + $$ + m = \{(A,1,2),(A,2,0),(B,2,3),(B,3,2)\}, + $$ $r$ не изменилось. + Обрабатываем $(A,1,2)$. + В данной ситуации второй цикл найдёт тройку $(B,2,3)$ и соответсвующее правило $S \to A \ B$. + Это значит, что и в $m$ и в $r$ добавится тройка $(S, 1, 3)$. + \item + Перед началом итерации + $$ + m = \{(A,2,0),(B,2,3),(B,3,2),(S,1,3)\}, + $$ + $$ + r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3)\}. + $$ + Обрабатываем $(A,2,0)$. + Внутринние циклы ничего не найдут, новых путей н появится. + \item + Перед началом итерации + $$ + m = \{(B,2,3),(B,3,2),(S,1,3)\}, + $$ + $$ + r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3)\}. + $$ + Обрабатываем $(B,2,3)$. + Первый цикл мог бы найти $(A,1,2)$, однако при проверке во вложенном цикле выяснится, что $(S, 1, 3)$ уже найдена. + В итоге, на данной итерации новых путей н появится. + \item + Перед началом итерации + $$ + m = \{(B,3,2),(S,1,3)\}, + $$ + $$ + r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3)\}. + $$ + Обрабатываем $(B,3,2)$. + Первый цикл найдёт $(S,1,3)$ и соответствующее правило $S_1 \to S \ B$. + Это значит, что и в $m$ и в $r$ добавится тройка $(S_1, 1, 2)$. + \item + Перед началом итерации + $$ + m = \{(S,1,3),(S_1, 1, 2)\}, + $$ + $$ + r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2)\}. + $$ + Обрабатываем $(S,1,3)$. + Второй цикл мог бы найти $(B,3,2)$, однако при проверке во вложенном цикле выяснится, что $(S_1, 1, 2)$ уже найдена. + В итоге, на данной итерации новых путей н появится. + \item + Перед началом итерации + $$ + m = \{(S_1, 1, 2)\}, + $$ + $$ + r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2)\}. + $$ + Обрабатываем $(S_1,1,2)$. + Первый цикл найдёт $(A,0,1)$ и соответствующее правило $S \to A \ S_1$. + Это значит, что и в $m$ и в $r$ добавится тройка $(S, 0, 2)$. + + \item + Перед началом итерации + $$ + m = \{(S, 0, 2)\}, + $$ + $$ + r= \{(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2)\}. + $$ + Обрабатываем $(S, 0, 2)$. + Найдено: $(B,2,3)$ и соответствующее правило $S_1 \to S \ B$. + B $m$ и в $r$ добавится тройка $(S_1, 0, 3)$. + + \item + Перед началом итерации + $$ + m = \{(S_1, 0, 3)\}, + $$ + \begin{align*} + r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ + &(S_1, 0, 3)\}. + \end{align*} + Обрабатываем $(S_1, 0, 3)$. + Найдено: $(A,2,0)$ и соответствующее правило $S \to A \ S_1$. + B $m$ и в $r$ добавится тройка $(S, 2, 3)$. + + \item + Перед началом итерации + $$ + m = \{(S, 2, 3)\}, + $$ + \begin{align*} + r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ + &(S_1, 0, 3),(S, 2, 3)\}. + \end{align*} + + Обрабатываем $(S, 2, 3)$. + Найдено: $(B,3,2)$ и соответствующее правило $S_1 \to S \ B$. + B $m$ и в $r$ добавится тройка $(S_1, 2, 2)$. + + \item + Перед началом итерации + $$ + m = \{(S_1, 2, 2)\}, + $$ + \begin{align*} + r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ + &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2)\}. + \end{align*} + Обрабатываем $(S_1, 2, 2)$. + Найдено: $(A,1,2)$ и соответствующее правило $S \to A \ S_1$. + B $m$ и в $r$ добавится тройка $(S, 1, 2)$. + + \item + Перед началом итерации + $$ + m = \{(S, 1, 2)\}, + $$ + \begin{align*} + r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ + &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2)\}. + \end{align*} + Обрабатываем $(S, 1, 2)$. + Найдено: $(B,2,3)$ и соответствующее правило $S_1 \to S \ B$. + B $m$ и в $r$ добавится тройка $(S_1, 1, 3)$. + + \item + Перед началом итерации + $$ + m = \{(S_1, 1, 3)\}, + $$ + \begin{align*} + r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ + &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2),(S_1, 1, 3)\}. + \end{align*} + Обрабатываем $(S_1, 1, 3)$. + Найдено: $(A,0,1)$ и соответствующее правило $S \to A \ S_1$. + B $m$ и в $r$ добавится тройка $(S, 0, 3)$. + + \item + Перед началом итерации + $$ + m = \{(S, 0, 3)\}, + $$ + \begin{align*} + r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ + &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2),(S_1, 1, 3),(S, 0, 3)\}. + \end{align*} + Обрабатываем $(S, 0, 3)$. + Найдено: $(B,3,2)$ и соответствующее правило $S_1 \to S \ B$. + B $m$ и в $r$ добавится тройка $(S_1, 0, 2)$. + + \item + Перед началом итерации + $$ + m = \{(S_1, 0, 2)\}, + $$ + \begin{align*} + r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ + &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2),(S_1, 1, 3),(S, 0, 3),(S_1, 0, 2)\}. + \end{align*} + Обрабатываем $(S_1, 0, 2)$. + Найдено: $(A,2,0)$ и соответствующее правило $S \to A \ S_1$. + B $m$ и в $r$ добавится тройка $(S, 2, 2)$. + + \item + Перед началом итерации + $$ + m = \{(S, 2, 2)\}, + $$ + \begin{align*} + r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ + &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2),(S_1, 1, 3),(S, 0, 3),(S_1, 0, 2),\\ + &(S, 2, 2)\}. + \end{align*} + Обрабатываем $(S, 2, 2)$. + Найдено: $(B,2,3)$ и соответствующее правило $S_1 \to S \ B$. + B $m$ и в $r$ добавится тройка $(S_1, 2, 3)$. + + \item + Перед началом итерации + $$ + m = \{(S_1, 2, 3)\}, + $$ + \begin{align*} + r= \{&(A,0,1),(A,1,2),(A,2,0),(B,2,3),(B,3,2),(S,1,3),(S_1, 1, 2),(S, 0, 2),\\ + &(S_1, 0, 3),(S, 2, 3),(S_1, 2, 2),(S, 1, 2),(S_1, 1, 3),(S, 0, 3),(S_1, 0, 2),\\ + &(S, 2, 2),(S_1, 2, 3)\}. + \end{align*} + Обрабатываем $(S_1, 2, 3)$. + Могло бы быть найдено: $(A,1,2)$ и соответствующее правило $S \to A \ S_1$, однако тройка $(S, 1, 3)$ уже есть в $r$. + А значит никаких новых троек найдено не будет и $m$ становится пустым. + Это была последняя итерация внешнего цикла, в $r$ на текущий момент уже содержится всё ршение. + + \end{enumerate} + +\end{example} + +Как можно заметить, количество итераций внешнего цикла также получилось достаточно большим. +Проверьте, зависит ли оно от порядка обработки элементов из $m$. +При этом внутренние циклы в нашем случае достаточно короткие, так как просматриваются только ``существенные'' элементы и избегается дублирование. + +%\section{Вопросы и задачи} +%\begin{enumerate} +% \item Проверить работу алгоритма CYK для цепочек на грамматике +% \begin{flushleft} +% $E \to E + E$ \\ +% $E \to E * E$ \\ +% $E \to (E)$ \\ +% $E \to n$ \\ +% \end{flushleft} +% и словах (алфавит $\Sigma = \{n, +, *, (, )\}$) +% \begin{flushleft} +% $ (n + n) * n$ \\ +% $ n + n * n$ \\ +% $n + n + n + n$ \\ +% $n + (n * n) + n$ \\ +% \end{flushleft} +% +% \item Изучить вычислительную сложность алгоритма CYK для матриц в зависимости от размера входного графа (размер грамматики считать фиксированным). +% +% \item Проверить работу алгоритма CYK для графов на графе +% +% \begin{center} +% \begin{tikzpicture}[node distance=3cm,shorten >=1pt,on grid,auto] +% \node[state] (q_0) {$0$}; +% \node[state] (q_1) [right=of q_0] {$1$}; +% \node[state] (q_2) [right=of q_1] {$2$}; +% \node[state] (q_3) [right=of q_2] {$3$}; +% \node[state] (q_4) [right=of q_3] {$4$}; +% \path[->] +% (q_0) edge node {$a$} (q_1) +% (q_1) edge node {$b$} (q_2) +% (q_2) edge node {$a$} (q_3) +% (q_3) edge node {$b$} (q_4) +% (q_1) edge[bend left, above] node {$b$} (q_3) +% (q_4) edge[bend left, below] node {$a$} (q_1); +% \end{tikzpicture} +% \end{center} +% +% И грамматике +% +% \begin{flushleft} +% $S \to S S$ \\ +% $S \to A B$ \\ +% $A \to a$ \\ +% $B \to b$ \\ +% \end{flushleft} +% +% \item Оцените временную сложность алгоритма Хеллингса и сравните её с оценкой для наивного обобщения CYK. +% +%\end{enumerate} diff --git a/tex/CombinatorsForCFPQ.tex b/tex/CombinatorsForCFPQ.tex new file mode 100644 index 0000000..ebf64e3 --- /dev/null +++ b/tex/CombinatorsForCFPQ.tex @@ -0,0 +1,28 @@ +\chapter{Комбинаторы для КС запросов} + +\section{Парсер комбинаторы} + +Что это, с чем едят, плюсы, минусы. Про семантику, безопасность, левую рекурсию и т.д. +Набор примитивных парсеров и функций, которые умеют из существующих арсеров строить более сложные (собственно, комбинаторы парсеров). + +Разобрать символ, разобрать последовательность, разобрать альтернативу. впринципе, этого достаточно, но это не очень удобно. + +Проблемы с левой рекурсией. +Существуют решения. Одно из них --- Meerkat. +Подробно про него? + +\section{Комбинаторы для КС запросов} + +Вообще говоря, идея использовать комбинаторы для навигации по графам достаточно очевидно и не нова. +немного про Trails~\cite{Kroni:2013:PGA:2489837.2489844}. + +Комбинаторы для запросов к графам на основе Meerkat~\cite{Verbitskaia:2018:PCC:3241653.3241655} + +Обобщённые запросы, типобезопасность и всё такое. +Примеры запросов. + +\section{Вопросы и задачи} +\begin{enumerate} + \item Реализовать библиотеку парсер комбинаторов. + \item Что-нибудь полезное с ними сделать. +\end{enumerate} diff --git a/tex/Conclusion.tex b/tex/Conclusion.tex new file mode 100644 index 0000000..cf3a14d --- /dev/null +++ b/tex/Conclusion.tex @@ -0,0 +1,7 @@ +\chapter{Заключение} + +Общие заключительные слова + +Про работы и частные случаи в статическом анализе, теоретическая сложность~\cite{10.1145/3571252, istomina2023finegrained}, свежие результаты и обзоры~\cite{10.1145/3583660.3583664}. + +Про то, что ещё интересного происходит в этой области, куда можно двигаться, ссылки на ключевые работы. diff --git a/tex/ConjunctiveAndBooleanLanguages.tex b/tex/ConjunctiveAndBooleanLanguages.tex new file mode 100644 index 0000000..2c8a84e --- /dev/null +++ b/tex/ConjunctiveAndBooleanLanguages.tex @@ -0,0 +1,235 @@ +\chapter{Конъюнктивные и булевы грамматики} + +Впервые конъюнктивные и булевы грамматики были предложены Александром Охотиным~\cite{DBLP:journals/jalc/Okhotin01,Okhotin:2003:BG:1758089.1758123}. Дадим определение конъюнктивной грамматики. + +\begin{definition} + \textit{Конъюнктивной грамматикой} называется $G = (\Sigma,N,P,S)$, где: + \begin{itemize} + \item $\Sigma$ и $N$ --- дизъюнктивные конечные непустые множества терминалов и нетерминалов. + \item $P$ --- конечное множество продукций, каждая вида + \[ + A\rightarrow \alpha_1\&...\&\alpha_n + \] + ,где $A \in N,n \geq 1$ и $\alpha_1,...,\alpha_n \in (\Sigma \cup N)^*$. + \item $S \in N$ --- стартовый нетерминал. + \end{itemize} +\end{definition} + +Конъюнктивная грамматика генерирует строки, выводя их из начального символа, так же, как это происходит в контекстно-свободных грамматиках в параграфе~\ref{CFG}. Промежуточные строки, используемые в процессе вывода, являются формулами следующего вида: + +\begin{definition}\label{Definition of conjunctive formula} + Пусть $G = (\Sigma,N,P,S)$ --- конъюнктивная грамматика. Множество конъюнктивных формул $ \mathcal{F}$ определяется индуктивно: + \begin{itemize} + \item Пустая строка $\varepsilon$ --- конъюнктивная формула. + \item Любой символ из $(\Sigma \cup N)$ --- формула. + \item Если $\mathcal{A}$ и $\mathcal{B}$ непустые формулы, тогда $\mathcal{AB}$ --- формула. + \item Если $\mathcal{A}_1,\ldots,\mathcal{A}_n$ $(n \geqslant 1)$ --- формула, тогда $(\mathcal{A}_1\&\ldots\&\mathcal{A}_n)$ --- формула. + \end{itemize} +\end{definition} + +\begin{definition} + Пусть $G = (\Sigma,N,P,S)$ --- конъюнктивная грамматика. Аналогично определению отношения непосредственной выводимости в контекстно-свободной грамматике~\ref{def derivability in CFG} определим $\xRightarrow[G]{}$ как отношение непосредственной выводимости на множестве конъюнктивных формул. + \begin{itemize} + \item Любой нетерминал в любой формуле может быть перезаписан телом любого правила для этого терминала заключенным в скобки. То есть для любых $s^{'},s^{''} \in (\Sigma \cup N \cup \{(, \&, )\})^*$ и $A\in N$, таких что $s^{'}As^{''}$ --- формула, и для всех правил вида $A \rightarrow \alpha_1\&\ldots\&\alpha_n \in P$, имеем $s^{'}As^{''}\xRightarrow[G]{}s^{'}(\alpha_1\&\ldots\&\alpha_n)s^{''}$. + \item Если формула содержит подформулу в виде конъюнкции одной или нескольких одинаковых терминальных строк, заключенных в скобки, тогда подформула может быть перезаписана терминальной строкой без скобок. То есть для любых $s^{'},s^{''} \in (\Sigma \cup N \cup \{(, \&, )\})^*$, $(n \geqslant 1)$ и $w \in \Sigma^*$, таких что $s^{'}(w\&\ldots\&w)s^{''}$ --- формула, имеем $s^{'}(w\&\ldots\&w)s^{''}\xRightarrow[G]{}s^{'}ws^{''}$. + \end{itemize} + Как и в случае контекстно-свободной грамматики обозначим $\xRightarrow[G]{}^*$ рефлексивное транзитивное замыкание отношения $\xRightarrow[G]{}$. +\end{definition} + +\begin{definition} + Пусть $G = (\Sigma,N,P,S)$ --- конъюнктивная грамматика. Язык, порождаемый формулой, это множество всех терминальных строк выводимых из этой формулы: $L_{G}(\mathcal{A}) = \{w\in\Sigma^* \mid \mathcal{A} \xRightarrow[G]{}^*w\}$. Очевидно, что язык порождаемый грамматикой, это язык порождаемый стартовым нетерминалом $S$ : $L(G) = L_{G}(S) = L(S)$. +\end{definition} + +\begin{theorem}\label{Theorem language generated by a formula} + Пусть $G = (\Sigma,N,P,S)$ --- конъюнктивная грамматика. Пусть $\mathcal{A}_1,\ldots,\mathcal{A}_n,\mathcal{B}$ --- формулы, $A \in N$, $a \in \Sigma$. Тогда, + \begin{enumerate} + \item $L(\varepsilon) = \{\varepsilon\}$. + \item $L(a) = \{a\}$. + \item $L(A) = \bigcup_{A \rightarrow \alpha_1\&\ldots\&\alpha_n \in P} L((\alpha_1\&\ldots\&\alpha_m))$. + \item $L(\mathcal{AB}) = L(\mathcal{A})*L(\mathcal{B})$ + \item $L((\mathcal{A}_1\&\ldots\&\mathcal{A}_n)) = \bigcap_{i = 1}^{n}L(\mathcal{A}_i)$. + \end{enumerate} +\end{theorem} + +Теорема~\ref{Theorem language generated by a formula} уже подразумевает интерпретацию грамматики как системы уравнений. Используем математический подход, чтобы лучше охарактеризовать конъюнктивные языки с помощью систем уравнений. + +\begin{definition}[Выражение] + Пусть $\Sigma$ конечный непустой алфавит. Пусть $X = \{X_1,\ldots,X_N\}$ вектор переменных. Выражение над алфавитом $\Sigma$, зависящее от переменных $X$, определяется индуктивно: + \begin{itemize} + \item $\varepsilon$ --- выражение. + \item Любой символ $a\in\Sigma$ --- выражение. + \item Любая переменная $X_i\in X$ --- выражение. + \item Если $\phi_1$ и $\phi_2$ выражения, то $\phi_1\phi_2, (\phi_1\mid\phi_2), (\phi_1\&\phi_2)$ также выражения. + \end{itemize} + Заметим, что любая формула, в терминах определения~\ref{Definition of conjunctive formula}, является выражением, где нетерминалы формулы это переменные выражения. С другой стороны, любое выражение, не содержащее дизъюнкции, формула. +\end{definition} + +Предположим, что переменные $X_i$ приняли в качестве значений слова из языка над алфавитом $\Sigma$. Определим значение всего выражения. + +\begin{definition}[Значение выражения]\label{Value of conjunctive expression} + Пусть $L = (L_1,\ldots,L_n) (L_i \subseteq \Sigma^*)$ вектор из $n$ языков над $\Sigma$, где $n \geqslant 1$. Пусть $\phi$ выражение над $\Sigma$, зависящее от переменных $X_1,\ldots,X_n$. Значение выражения $\phi$ на векторе $L$ --- это язык над тем же алфавитом $\Sigma$. Обозначим его $\phi(L)$ и определим индуктивно на структуре выражения: + \begin{itemize} + \item $\varepsilon(L) = \{\varepsilon\}$. + \item $a(L) = \{a\}$ для любого $a\in\Sigma$. + \item $X_i(L) = L_i$ для любого $X_i \in X$. + \item $\phi_1\phi_2 = \phi_1(L) * \phi_2(L), (\phi_1\mid\phi_2)(L) = \phi_1(L) \cup \phi_2(L), (\phi_1\&\phi_2)(L) = \phi_1(L) \cap \phi_2(L)$ для любых выражений $\phi_1$ и $\phi_2$. + \end{itemize} +\end{definition} + +Обобщим определение~\ref{Value of conjunctive expression} на случай вектора выражений. + +\begin{definition}[Значение вектора выражений] + Пусть $L = (L_1,\ldots,L_n) (L_i \subseteq \Sigma^*)$ вектор из $n$ языков над $\Sigma$, где $n \geqslant 1$. Пусть $\phi_1,\ldots,\phi_m$ выражения над $\Sigma$, зависящее от переменных $X_1,\ldots,X_n$. Значение вектора выражений $P = (\phi_1,\ldots,\phi_m)$ на векторе $L$ --- это вектор языков $P(L) = (\phi_1(L),\ldots,\phi_m(L))$ над тем же алфавитом $\Sigma$. +\end{definition} + +Зададим частичный порядок относительно включения $``\preccurlyeq"$ на множестве языков и расширим его на вектора языков длины $n$: $(L_1^{'},\ldots,L_n^{'})\preccurlyeq(L_1^{''},\ldots,L_n^{''})$ если и только если $L_i^{'} \subseteq L_i^{''}$ для любого $1\leqslant i \leqslant n$ + +\begin{definition}\label{Definition a conjuctive system of equations} + $X = P(X)$ система уравнений над алфавитом $\Sigma$ и $X = \{X_1,\ldots,X_n\}$, где $P = (\phi_1,\ldots,\phi_n)$ вектор выражений над алфавитом $\Sigma$, зависящий от $X$. + + Вектор языков $L = (L_1,\ldots,L_n)$ является решением системы уравнений если $L = P(L)$. + + Наименьшее решение $L$ это вектор языков, такой что для любого другого сравнимого вектора языков $L^{'}$ выполняется $L \preccurlyeq L^{'}$. +\end{definition} + +Заметим, что оператор $P$ на множестве $2^{\Sigma}\times\ldots\times2^{\Sigma}$, что решение системы~\ref{Definition a conjuctive system of equations} это неподвижная точка $P$ и что наименьшее решение системы это наименьшая неподвижная точка оператора $P$. + +\begin{theorem}\label{Theorem of a least fixed point solution} + Для любой системы из определения~\ref{Definition a conjuctive system of equations} с переменными $X_1,\ldots,X_n$, оператор $P = (\phi_1,\ldots,\phi_n)$ имеет наименьшую неподвижную точку $L = (L_1,\ldots,L_n) = \lim_{i\to\infty}P^{i}\underbrace{(\varnothing,\ldots,\varnothing)}_n$. +\end{theorem} + +Приведем пример конъюнктивной грамматики. + +\begin{example}[Пример конъюнктивной грамматики] + Следующая конъюнктивная грамматика $G$ порождает язык $\{a^nb^nc^n\mid n \geq 0\}$: + + \begin{align*} + 1.\ S &\to A B \& D C \\ + 2.\ A &\to a A \mid \varepsilon \\ + 3.\ B &\to b B c \mid \varepsilon \\ + 4.\ C &\to c C \mid \varepsilon \\ + 5.\ D &\to aDb \mid \varepsilon + \end{align*} + + Легко видеть, что $L(AB) = \{a^ib^jc^k\mid j = k\}$ и $L(DC) = \{a^ib^jc^k\mid i = j\}$. Тогда $L(S) = L(AB) \cap L(DC) = \{a^nb^nc^n\mid n \geq 0\}$. + + В этой грамматике строка $abc$ может быть получена следующим образом. Для начала представим грамматику в виде системы уравнений: + \begin{align*} + S &= A B \cap D C \\ + A &= \{a\}A \cup \varepsilon \\ + B &= \{b\}B\{c\} \cup \varepsilon \\ + C &= \{c\}C \cup \varepsilon \\ + D &= \{a\}D\{b\} \cup \varepsilon + \end{align*} + Используя теорему~\ref{Theorem of a least fixed point solution}, будем итеративно вычислять $P^{i}\underbrace{(\varnothing,\ldots,\varnothing)}_5$. На каждом шаге будем подставлять все терминальные строки из языков, порожденных нетерминалами на предыдущем шаге, в соответствующие нетерминалы правой части каждого уравнения и записывать получившиеся терминальные строки в языки нетерминалов текущего шага. Продолжаем до тех пор пока язык, порождаемый нетерминалом $S$, не будет содержать терминальную строку $``abc''$. + \begin{enumerate} + \item На начальном этапе имеем $P^{0}(\varnothing,\ldots,\varnothing) = (S: \varnothing, A: \varnothing, B: \varnothing, C: \varnothing, D: \varnothing)$ + \item Подставляем в первое уравнение терминальные строки из шага 1 в соответствующие нетерминалы, т.е. + \begin{align*} + S: \varnothing &= \varnothing\varnothing \cap \varnothing\varnothing \\ + A: \{\varepsilon\} &= \{a\}\varnothing \cup \{\varepsilon\} \\ + B: \{\varepsilon\} &= \{b\}\varnothing\{c\} \cup \{\varepsilon\} \\ + C: \{\varepsilon\} &= \{c\}\varnothing \cup \{\varepsilon\} \\ + D: \{\varepsilon\} &= \{a\}\varnothing\{b\} \cup \{\varepsilon\} + \end{align*} + В конце итерации получаем $P^{1}(\varnothing,\ldots,\varnothing) = (S: \varnothing, A: \{\varepsilon\}, B: \{\varepsilon\}, C: \{\varepsilon\}, D: \{\varepsilon\})$ + \item Делаем еще одну итерацию, + \begin{align*} + S: \{\varepsilon\} &= \{\varepsilon\}\{\varepsilon\} \cap \{\varepsilon\}\{\varepsilon\} \\ + A: \{a, \varepsilon\} &= \{a\}\{\varepsilon\} \cup \{\varepsilon\} \\ + B: \{bc, \varepsilon\} &= \{b\}\{\varepsilon\}\{c\} \cup \{\varepsilon\} \\ + C: \{c, \varepsilon\} &= \{c\}\{\varepsilon\} \cup \{\varepsilon\} \\ + D: \{ab, \varepsilon\} &= \{a\}\{\varepsilon\}\{b\} \cup \{\varepsilon\} + \end{align*} + В конце итерации получаем $P^{2}(\varnothing,\ldots,\varnothing) = (S: \{\varepsilon\}, A: \{a, \varepsilon\}, B: \{bc, \varepsilon\}, C: \{c, \varepsilon\}, D: \{ab, \varepsilon\})$ + \item Еще одна итерация, + \begin{align*} + S: \{\fbox{abc}, \varepsilon\} &= \{a, \varepsilon\}\{bc, \varepsilon\} \cap \{ab, \varepsilon\}\{c, \varepsilon\} \\ + A: \{a, aa, \varepsilon\} &= \{a\}\{a, \varepsilon\} \cup \{\varepsilon\} \\ + B: \{bc, bbcc, \varepsilon\} &= \{b\}\{bc, \varepsilon\}\{c\} \cup \{\varepsilon\} \\ + C: \{c, cc, \varepsilon\} &= \{c\}\{c, \varepsilon\} \cup \{\varepsilon\} \\ + D: \{ab, aabb, \varepsilon\} &= \{a\}\{ab, \varepsilon\}\{b\} \cup \{\varepsilon\} + \end{align*} + В конце итерации получили $P^{3}(\varnothing,\ldots,\varnothing) = (S: \{\fbox{abc}, \varepsilon\}, A: \{a, aa, \varepsilon\}, B: \{bc, bbcc, \varepsilon\}, C: \{c, cc, \varepsilon\}, D: \{ab, aabb, \varepsilon\})$. Заметим, что терминальная строка $``abc"$ появилась в языке, который порождает стартовый нетерминал $S$. Т.е. терминальная строка $``abc"$ выводима в грамматике $G$, что и требовалось показать. + \end{enumerate} + + Заметим, что строку $``abc"$ также можно получить применением правил вывода. здесь цифра над стрелкой соответствует номеру примененного правила. + \begin{align*} + S &\xRightarrow{1}(AB\&DC) \\ + &\xRightarrow{2}(aAB\&DC) \xRightarrow{2} (a\varepsilon B\&DC) \\ + &\xRightarrow{3}(abBc\&DC) \xRightarrow{3}(ab\varepsilon c\&DC) \\ + &\xRightarrow{5}(abc\&aDbC) \xRightarrow{5}(abc\&a\varepsilon bC) \\ + &\xRightarrow{4}(abc\&abcC) \xRightarrow{4}(abc\&abc\varepsilon) \\ + &\Rightarrow(abc\&abc) \Rightarrow abc + \end{align*} +\end{example} + +\begin{example} + Конъюнктивная грамматика $G$ для языка $L = \{wcw \mid w \in \{a, b\}^*\}$: + \begin{align*} + S &\to C \& D \\ + C &\to aCa \mid aCb \mid bCa \mid bCb \mid c \\ + D &\to aA\&aD \mid bB\&bD \mid cE \\ + A &\to aAa \mid aAb \mid bAa \mid bAb \mid cEa \\ + B &\to aBa \mid aBb \mid bBa \mid bBb \mid cEb \\ + E &\to aE \mid bE \mid \varepsilon + \end{align*} +\end{example} + +Подробнее о конъюнктивных грамматиках можно прочитать в статьях~\cite{DBLP:journals/jalc/Okhotin01, Okhotin2002, DBLP:journals/tcs/Okhotin03a, f60a33d409364914be560cac0e54b12c}. + +Дадим определение булевой грамматики. + +\begin{definition} + \textit{Булевой грамматикой} называется $G = (\Sigma,N,P,S)$, где: + \begin{itemize} + \item $\Sigma$ и $N$ --- дизъюнктивные конечные непустые множества терминалов и нетерминалов. + \item $P$ --- конечное множество продукций, каждая вида + \[ + A\rightarrow \alpha_1\&...\&\alpha_m\&\neg\beta_1\&...\&\neg\beta_n + \] + ,где $A \in N, m, n >=0, m+n \geq 1$ и $\alpha_i,\beta_j \in (\Sigma \cup N)^*$. + \item $S \in N$ --- стартовый нетерминал. + \end{itemize} +\end{definition} + +Приведем пример булевой грамматики. + +\begin{example} + Следующая булева грамматика порождает язык $\{a^mb^nc^n\mid m,n \geq 0, m \neq n \}$: + + \begin{align*} + S &\to A B \& \neg D C \\ + A &\to a A \mid \varepsilon \\ + B &\to b B c \mid \varepsilon \\ + C &\to c C \mid \varepsilon \\ + D &\to aDb \mid \varepsilon + \end{align*} + + Очевидно, что $L(AB) = \{a^mb^nc^n\mid m,n \in \mathbb{N}\}$ и $L(DC) = \{a^nb^nc^m\mid m,n \in \mathbb{N}\}$. Тогда $L(AB)\cap\overline{L(DC)} = \{a^mb^nc^n\mid m,n \geq 0, m \neq n \}$. +\end{example} + +Подробнее о булевых грамматиках можно прочитать в статьях~\cite{Okhotin:2003:BG:1758089.1758123,Okhotin:2014:PMM:2565359.2565379}. + +Определим бинарную нормальную форму конъюнктивной грамматики. +\begin{definition}[Бинарная нормальная форма] + Конъюнктивная грамматика $G = (\Sigma, N, P, S)$ находится в бинарной нормальной форме, если каждое правило из P имеет вид, + \begin{itemize} + \item $A \rightarrow B_1 C_1 \& \ldots\& B_m C_m$, где $m \geqslant 1; A,B_i,C_i \in N$. + \item $A \rightarrow a$, где $A \in N, a \in \Sigma$. + \item $S \rightarrow \varepsilon$, если только $S$ не содержится в правой части всех правил. + \end{itemize} +\end{definition} + +\begin{theorem}\label{Binary normal form conjunctive grammar theorem} + Для каждой конъюнктивной грамматики $G$ можно построить конъюнктивную грамматику в бинарной нормальной форме $G^{'}$, такую что $L(G) = L(G^{'})$. +\end{theorem} +Доказательство теоремы~\ref{Binary normal form conjunctive grammar theorem} описано в статье~\cite{DBLP:journals/jalc/Okhotin01}. + + + +%\section{Вопросы и задачи} +%\begin{enumerate} +% \item !!! +% \item !!! +%\end{enumerate} diff --git a/tex/DerivativesForCFPQ.tex b/tex/DerivativesForCFPQ.tex new file mode 100644 index 0000000..8b9d1e7 --- /dev/null +++ b/tex/DerivativesForCFPQ.tex @@ -0,0 +1,156 @@ +\chapter{Производные для КС запросов}\label{chpt:CFPQ_Derivatives} + +В данной главе мы рассмотрим производные Бжозовского и их возможное применение. + +\section{Производные} + +Впервые производные формальных языков были определены в 1964 году учёным Янушем Бжозовским (в честь него они и были названы). Он определил это понятие для регулярных языков, предложил алгоритм для вычисления производной обобщенного регулярного выражения, также Бжозовский занимался исследованием свойств производных {\cite{Brzozowski1964}}. + +Изначально всё начиналось с производных регулярных языков, и в главе мы в основном будем говорить именно о них. + +Рассмотрим формальное определение производной произвольного языка: + +\begin{definition} + \textit{Производной языка $\mathcal{L}$ по символу а} называется язык $\mathcal{L'} = \partial_{a}(\mathcal{L}) = \{w \mid aw \in \mathcal{L}\}$, где: + \begin{itemize} + \item $\mathcal{L} \subseteq \{w \mid w \in \Sigma^*\}$ --- произвольный язык над алфавитом $\Sigma$ + \item $a \in \Sigma$ --- символ, по которому берётся производная + \end{itemize} + То есть фактически производная языка --- это суффиксы слов, начинающихся на символ, по которому язык дифференцируется. +\end{definition} + +\begin{example}[Производные языка] +Рассмотрим язык $\mathcal{L} = \{pen, plain, day, pray\}$ и несколько языков, порождённых от него с помощью дифференцирования: +\begin{enumerate} + \item $\mathcal{L'} = \partial_{p}(\mathcal{L}) = \{en, lain, ray\}$ + \item $\mathcal{L''} = \partial_{e}(\mathcal{L'}) = \{n\}$ + \item $\mathcal{L'''} =\partial_{n}(\mathcal{L''}) = \{\varepsilon\}$ +\end{enumerate} +\end{example} + +\section{Принадлежность языку} + +С помощью производных ествественным образом можно проверять принадлежность слова регулярному языку. +Есть регулярное выражение $R$ и язык, порожденный этим регулярным выражением $L(R)$. Возьмём произвольное слово $w$ и зададимся вопросом: $w \in L(R)$? + +Пусть $w = a_{0}a_{1}... a_{n-1}$, а новый язык $\mathcal{L'}$ получен последовательным дифференцирование исходного языка $L(R)$ по каждому из символов слова $w$, то есть $\mathcal{L'} = \partial_{a_{n-1}}(...\partial_{a_{1}}(\partial_{a_{0}}(L(R)))...)$. В таком случае принадлежность $w$ языку $L(R)$ определяется наличием пустого слова в итоговом языке: $\varepsilon \in \mathcal{L'} \Rightarrow w \in L(R)$. + +\begin{example} +Дан язык $\mathcal{L} = \{pen, plain, day, pray\}$. Принадлежат ли данному языку слова $pen$, $pet$? +\begin{itemize} + \item $\partial_{p}(\mathcal{L}) = \{en, lain, ray\} \Rightarrow \partial_{e}(\partial_{p}(\mathcal{L})) = \{n\} \Rightarrow \partial_{n}(\partial_{e}(\partial_{p}(\mathcal{L}))) = \{\varepsilon\}$. А значит, $pen \in \mathcal{L}$ + \item $\partial_{p}(\mathcal{L}) = \{en, lain, ray\} \Rightarrow \partial_{e}(\partial_{p}(\mathcal{L})) = \{n\} \Rightarrow \partial_{t}(\partial_{e}(\partial_{p}(\mathcal{L}))) = \emptyset$. Значит, $pet \notin \mathcal{L}$ +\end{itemize} + +\end{example} + +Описанный выше механизм является основной идеей всех алгоритмом, которые стоятся на производных. + +\section{Построение производных} + +Концептуально понятно, как выглядят производные, но хотелось бы уметь считать их алгоритмически, причём сохраняя конструктивное представление языка. Например, для КС грамматики, вычисляя её производную, строится другая КС грамматика. + +Рассмотрим алгоритм вычисления производной для регулярных языков, которые представлены как регулярные выражения. Пусть $r_{1}$ и $r_{2}$ --- два регулярных выражения, $a$ --- произвольный терминальный символ. Определим вспомогательную функцию N --- Nullable, которая проверяет язык на содержание в нём пустого слова $\varepsilon$: + +\begin{align*} + N(\varepsilon) &= true \\ + N(a) &= false \\ + N(r_{1} \cdot r_{2}) &= N(r_{1}) \land N(r_{2}) \\ + N(r_{1} \mid r_{2}) &= N(r_{1}) \lor N(r_{2}) \\ + N(r^*) &= true +\end{align*} + +Теперь мы готовы перейти непосредственно к вычислению производной по символу $a$: + +\begin{align*} + \partial_{a}(\emptyset) &= \emptyset \\ + \partial_{a}(\varepsilon) &= \emptyset \\ + \partial_{a}(b) &= \begin{cases} + \emptyset, & \mbox{if } a \neq b \\ + \varepsilon, & \mbox{otherwise} \end{cases} \\ + \partial_{a}(r_{1} \cdot r_{2}) &= \begin{cases} + \partial_{a}(r_{1}) \cdot r_{2} \mid \partial_{a}(r_{2}) & \mbox{if } N(r_{1}) = \mbox{true} \\ + \partial_{a}(r_{1}) \cdot r_{2}, & \mbox{otherwise} \end{cases} \\ + \partial_{a}(r_{1} \mid r_{2}) &= \partial_{a}(r_{1}) \mid \partial_{a}(r_{2}) \\ + \partial_{a}(r^*) &= \partial_{a}(r) \cdot r^* +\end{align*} + +Все правила, за исключением, может быть, последнего, достаточно тривиальны. Последнее доказывается по индукции, но особо любопытные могут руками вычислить для первой пары слагаемых и рассмотреть закономерность. + +Приводить подобный алгоритм для КС языков мы не будем, но важно понимать, что он есть, и идея не сильно отличается от алгоритма для регулярных языков. + +\section{Задача достижимости} +Используя производные, можно решать задачу достижимости. Даны регулярный запрос и граф, для простоты зафиксируем стартовую вершину. Для решения задачи достижимости при помощи производных рекурсивно выполняем следующее: + +\begin{enumerate} + \item При переходе по ребру дифференцируем запрос по метке на нём + \item Передаём эту производную вдоль ребра в следующую вершину + \item В этой следующей вершине производная запоминается, если ранее не встречалось регулярное выражение, которое порождается тот же язык (таким образом формируется набор регулярных выражений, порождающих языки, которые уже передовались на вершину). В противном случае -- терминируемся. +\end{enumerate} + +После того, как вышеописанный алгоритм завершился для всех вершин, проходим по ним и ищем в их наборах Nullable регулярные выражения, которые и сигнализируют о том, что путь из стартовой веришны в данную вершину существует. + +Некоторые замечания: + +\begin{itemize} + \item Если алгоритм запускается не на одной вершине, а сразу на нескольких, передаются вдоль рёбер не просто производные, а пары: (стартовая вершина, производная). + \item Что мы в общем случае делаем с циклами, чтобы задача считалась алгоритмически? Разбиваем граф на наибольшие по включению компоненты сильной связности с связями между ними, стягиваем компоненты. Тогда граф превращается в дек, в котором проблем с нетерминируемостью нет, а с компонентами сильной связности разбираемся отдельно. Для этого достаточно рассмотреть одну такую компоненту: если есть цикл, то по нему можно ходить, только если в запросе есть применение звезды Клини, и, как нам уже известно, производная запроса данной операции --- конечная конструкция. В итоге мы сможем, переходя по вершинами, прийти к моменту, когда внутри компоненты в наборах производных вершин новых элементов не будет прибавляться, а значит, мы можем закончить алгоритм. +\end{itemize} + +Рассмотрим решение задачи достижимости с помощью производных на конкретном примере: + +\begin{example} +Даны регулярный запрос $R = a^* \mid a^* \cdot b$ и граф $\mathcal{G}$: + + \begin{center} + \begin{tikzpicture}[shorten >=1pt,on grid,auto] + \node[state] (q_0) {$0$}; + \node[state] (q_1) [above right=of q_0] {$1$}; + \node[state] (q_2) [right=of q_0] {$2$}; + \node[state] (q_3) [right=of q_2] {$3$}; + \path[->] + (q_0) edge node {a} (q_1) + (q_1) edge node {a} (q_2) + (q_2) edge node {a} (q_0) + (q_2) edge[bend left, above] node {b} (q_3) + (q_3) edge[bend left, below] node {b} (q_2); + \end{tikzpicture} + \end{center} + +Стартовая веришина --- вершина графа $\mathcal{G}$ с индексом 0. Хотим проверить существование путей из вершины 0 до других вершин графа по $R$. Заведем 4 множества, в которых будем хранить регулярные выражения, передаваемые в конкретную вершину: $M_{0}$ --- для вершины с индексом 0, $M_{1}$ --- для вершины с индексом 1 и так далее. + +\begin{enumerate} + \item Начинаем идти вдоль ребра с меткой $a$ из вершины 0 в 1. Дифференцируем наш запрос по данной метке: $\partial_{a}(R) = \partial_{a}(a^* \mid a^* \cdot b) = \partial_{a}(a^*) \mid \partial_{a}(a^* \cdot b) = \partial_{a}(a) \cdot a^* \mid \partial_{a}(a^*) \cdot b \mid \partial_{a}(b) = a^* \mid a^* \cdot b = R$. Запоминаем эту производную в $M_{1}$: $M_{1} = \{R\}$ + \item Аналогично идём из вершины 1 в вершину 2 по $a$. В итоге в $M_{2}$ также будет находиться R. + \item В вершине 2 параллельно идём по метке $a$ в 0 и по метке $b$ в вершину с индексом 3. + \begin{enumerate} + \item В первом потоке при переходе по $a$ мы дифференцируем $R$ по a, получаем также $R$, кладем его в $M_{0}$. Пытаясь продолжить эти вычисления в данном потоке, мы обнаружим, что при переходе по $a$ из вершины 0 в вершину 1 наша производная будет снова R, но в множестве $M_{1}$ $R$ уже находится, а значит, данная ветка вычислений терминируется. + \item При переходе по $b$ диффиринцируем переданную производную $R$: $\partial_{b}(R) = \partial_{b}(a^* \mid a^* \cdot b) = \partial_{b}(a^*) \mid \partial_{b}(a^* \cdot b) = \partial_{b}(a) \cdot a^* \mid \partial_{b}(a^*) \cdot b \mid \partial_{b}(b) = \partial_{b}(b) = \varepsilon$. Запоминаем производную в $M_{3}$: $M_{3} = \{\varepsilon\}$. Дифференцируем её по $b$ при переходе из 3 в 2. Кладём в $M_{2}$ $\partial_{b}(\varepsilon) = \emptyset$. Tаким oбразом, $M_{2} = \{R, \emptyset\}$. На данном этапе можно терминирироваться, т.к. для достижимости нам интересны регулярные выражения, порождающий $\varepsilon$, но дифференцируя $\emptyset$ по каким-либо меткам, мы снова получаем $\emptyset$. При "честном" вычислении, в нашем случае пустое множество будет добавлено во все множества $M_{i}$, и уже после этого вычисление завершится. + \end{enumerate} + \item Теперь у нас есть сформированные множества производных для всех вершин и мы можем говорить о достижимости до данных вершин из стартовой. Рассмотрим $M_{0}$, $M_{0} = \{R\}$. Содержит ли $R$ $\varepsilon$? Посчитаем для этого нашу функцию Nullable: $N(R) = N(a^* \mid a^* \cdot b) = N(a^*) \mid N(a^* \cdot b) = true \mid N(a^* \cdot b) = true$. Из чего следует, что существует путь из вершины 0 в вершину 0. Аналогичным способом заключаем, что веришны 2 и 3 достижимы из вершины 0 (т.к. в их множества также содержится $R$). Рассмотрим $M_{3} = \{\varepsilon\}$. $N(\varepsilon) = true$, значит, вершина 3 тоже достижима из 0. Алгоритм завершён. +\end{enumerate} + +Таким образом, выполнив указанный выше алгоритм для данного примера, мы определили, что из стартовой вершины с индексом 0 достижимы все вершины графа $\mathcal{G}$. +\end{example} + +\section{Парсинг на производных} + +Статьи~\cite{DBLP:journals/corr/abs-1010-5023,Adams:2016:CPP:2908080.2908128,Might:2011:PDF:2034574.2034801,andersenparsing} +Реализации. +На Scala~\footnote{\url{https://github.com/djspiewak/parseback}}, на Racket~\footnote{\url{https://bitbucket.org/ucombinator/derp-3/src/86bca8a720231e010a3ad6aefd1aa1c0f35cbf6b/src/derp.rkt?at=master&fileviewer=file-view-default}}. + +\section{Адаптация для КС запросов} + +Для регулярных запросов над графами~\cite{Nole:2016:RPQ:2949689.2949711}. +Хорошо работают в распределённых системах, в которых реализовван параллелизм уровня вершин. +Например Google Pregel. + + + +\section{Вопросы и задачи} +\begin{enumerate} + \item Предъявить несколько выводов для одной цепочки. + \item Построить выводы + \item Построить деревья вывода !!! Перенести из раздела про SPPF +\end{enumerate} + diff --git a/tex/FLPQ.tex b/tex/FLPQ.tex new file mode 100644 index 0000000..22dfdda --- /dev/null +++ b/tex/FLPQ.tex @@ -0,0 +1,146 @@ +\chapter[Пути с ограничениями в терминах формальных языков]{Задача о поиске путей с ограничениями в терминах формальных языков}\label{chpt:FLPQ} + + + +В данной главе сформулируем постановку задачи о поиске путей в графе с ограничениями. +Также мы приведём несколько примеров областей, в которых применяются алгоритмы решения этой задачи. + +\section{Постановка задачи } + + +Пусть нам дан конечный ориентированный помеченный граф $\mathcal{G}=\langle V,E,L \rangle$. +Функция $\omega(\pi) = \omega((v_0, l_0, v_1),(v_1,l_1,v_2),\dots,(v_{n-1},l_{n-1},v_n)) = l_0 \cdot l_1 \cdot \ldots \cdot l_{n-1} $ строит слово по пути посредством конкатенации меток рёбер вдоль этого пути. +Очевидно, для пустого пути данная функция будет возвращать пустое слово, а для пути длины $n > 0$ --- непустое слово длины $n$. + +Если теперь рассматривать задачу поиска путей, то окажется, что то множество путей, которое мы хотим найти, задаёт множество слов, то есть язык. +А значит, критерий поиска мы можем сформулировать следующим образом: нас интересуют такие пути, что слова, составленные из меток вдоль них, принадлежат заданному языку. +\begin{definition} \label{def1} + \textit{Задача поиска путей с ограничениями в терминах формальных языков} заключается в поиске множества путей $\Pi = \{\pi \mid \omega(\pi) \in \mathcal{L}\}$. + +\end{definition} + +В задаче поиска путей мы можем накладывать дополнительные ограничения на путь (например, чтобы он был простым, кратчайшим или Эйлеровым~\cite{kupferman2016eulerian}), но это уже другая история. + +Другим вариантом постановки задачи является задача достижимости. + +\begin{definition} \label{def2} + \textit{Задача достижимости} заключается в поиске множества пар вершин, для которых найдется путь с началом и концом в этих вершинах, что слово, составленное из меток рёбер пути, будет принадлежать заданному языку. + $\Pi' = \{(v_{i}, v_{j}) \mid \exists v_{i} \pi v_{j}, \omega(\pi) \in \mathcal{L}\}$. + +\end{definition} + +При этом, множество $\Pi$ может являться бесконечным, тогда как $\Pi'$ конечно, по причине конечности графа $\mathcal{G}$. + +Язык $\mathcal{L}$ может принадлежать разным классам и быть задан разными способами. Например, он может быть регулярным, контекстно-свободным, или многокомпонентным контекстно-свободным. + +Если $\mathcal{L}$ --- регулярный, $\mathcal{G}$ можно рассматривать как недетерминированный конечный автомат (НКА), в котором все вершины являются одновременно и стартовыми, и конечными. +Тогда задача поиска путей, в которой $\mathcal{L}$ --- регулярный, сводится к пересечению двух регулярных языков. + +Более подробно мы рассмотрим случай, когда $\mathcal{L}$ --- контекстно-свободный язык. + +Путь $G = \langle \Sigma, N, P \rangle$ --- контекстно-свободная грамматика. +Будем считать, что $L \subseteq \Sigma$. +Мы не фиксируем стартовый нетерминал в определении грамматики, поэтому, чтобы описать язык, задаваемый ей, нам необходимо отдельно зафиксировать стартовый нетерминал. +Таким образом, будем говорить, что $L(G,N_i) = \{ w \mid N_i \xRightarrow[G]{*} w \}$ --- это язык задаваемый грамматикой $G$ со стартовым нетерминалом $N_i$. + +\begin{example} + Пример задачи поиска путей. + + Дана грамматика $G$, задающая язык $\mathcal{L} = a^n b^n$: + \begin{align*} + S &\to a b \\ + S &\to a S b + \end{align*} + И дан граф $\mathcal{G}:$ + \begin{center} + \input{figures/graph/graph0.tex} + \end{center} + + Кратчайшими путями, принадлежащими множеству $\Pi = \{\pi \mid \omega(\pi) \in \mathcal{L}\}$, являются: + + \begin{center} + \input{figures/flpq/path1.tex} + \end{center} + + \begin{center} + \input{figures/flpq/path2.tex} + \end{center} + +\end{example} + + +\section{О разрешимости задачи} + +Задачи из определения \ref{def1} и \ref{def2} сводятся к построению пересечения языка $\mathcal{L}$ и языка, задаваемого путями графа, $R$. +А мы для обсуждения разрешимости задачи рассмотрим более слабую постановку задачи: + +\begin{definition} + Необходимо проверить, что существует хотя бы один такой путь $\pi$ для данного графа, для данного языка $\mathcal{L}$, что $\omega(\pi) \in \mathcal{L}$. + +\end{definition} + +Эта задача сводится к проверке пустоты пересечения языка $\mathcal{L}$ c $R$ --- регулярным языком, задаваемым графом. От класса языка $\mathcal{L}$ зависит её разрешимость: + +\begin{itemize} + \item Если $\mathcal{L}$ регулярный, то получаем задачу пересечения двух регулярных языков: + + $\mathcal{L} \cap R = R'$. + $R'$ --- также регулярный язык. + Проверка регулярного языка на пустоту --- разрешимая проблема. + + \item Если $\mathcal{L}$ контекстно-свободный, то получаем задачу + + $\mathcal{L} \cap R = CF$ --- контекстно-свободный. + Проверка контекстно-свободного языка на пустоту --- разрешимая проблема. + + \item Помимо иерархии Хомского существуют и другие классификации языков. + Так например, класс конъюнктивных (Conj) + языков~\cite{DBLP:journals/jalc/Okhotin01} + является строгим расширением контекстно-свободных языков и все так же позволяет полиномиальный синтаксический анализ. + + Пусть $\mathcal{L}$ --- конъюнктивный. При пересечении конъюнктивного и регулярного языков получается конъюнктивный ($\mathcal{L} \cap R = Conj$), а проблема проверки Conj на пустоту не разрешима~\cite{DBLP:journals/tcs/Okhotin03a}. + + \item Ещё один класс языков из альтернативной иерархии, не сравнимой с Иерархией Хомского, --- MCFG (multiple context-free grammars)~\cite{SEKI1991191}. + Как его частный случай --- TAG (tree adjoining grammar)~\cite{Joshi1997}. + + Если $\mathcal{L}$ принадлежит классу MCFG, то $\mathcal{L} \cap R$ также принадлежит MCFG. Проблема проверки пустоты MCFG разрешима~\cite{SEKI1991191}. + +\end{itemize} + +Существует ещё много других классификаций языков, но поиск универсальной иерархии до сих пор продолжается. + +Далее, для изучения алгоритмов решения, нас будет интересовать задача $R \cap CF$. + +\section{Области применения} + +Поиск путей с ограничениями в виде формальных языков широко применяется в различных областях. Ниже даны ключевые работы по применению поиска путей с контекстно-свободными ограничениями и ссылки на них для более детального ознакомления. + +\begin{itemize} + \item Межпроцедурный Статанализ кода. + Идея начала активно разрабатываться Томасом Репсом~\cite{Reps}. Далее последовал ряд, в том числе инженерных работ, применяющих достижимость с контекстно-свободными ограничениями для анализа указателей, анализа алиасов и других прикладных задач~\cite{LabelFlowCFLReachability,specificationCFLReachability,Zheng}. + \item Графовые БД. Впервые задача сформулирована Михалисом Яннакакисом~\cite{Yannakakis}. Запросы с контекстно-свободными ограничениями нашли своё применение различных областях. + \begin{itemize} + \item Социальные сети~\cite{Hellings2015PathRF}. + \item RDF обработка~\cite{10.1007/978-3-319-46523-4_38}. + \item Биоинформатика~\cite{cfpqBio}. + \end{itemize} + +\end{itemize} + +%\begin{itemize} +% \item OpenCypher~\cite{Kuijpers:2019:ESC:3335783.3335791} +% \item J.Hellings. CFPQ~\cite{hellingsRelational,hellings2015querying,Hellings2015PathRF} +% \item Zhang. CFPQ on rdf graphs~\cite{10.1007/978-3-319-46523-4_38} +% \item Bradford~\cite{bradford2007quickest,ward2008distributed,bradford2016fast,Bradford:2008:LCG:1373936.1373946} +%\end{itemize} + + +%\section{Вопросы и задачи} +%\begin{enumerate} +% \item Пусть есть граф. Задайте грамматику для поиска всех путей, таких, что.... +% \item Существует ли в графе !!! путь из А в Б, такой что!!! +% \item Для графа !!! постройте все пути, удовлетворяющие !!!! +% +% \item Задача 1 +% \item Задача 2 +%\end{enumerate} diff --git a/tex/GLL-based_CFPQ.tex b/tex/GLL-based_CFPQ.tex new file mode 100644 index 0000000..2f5f7dd --- /dev/null +++ b/tex/GLL-based_CFPQ.tex @@ -0,0 +1,647 @@ +\chapter{Алгоритм на основе нисходящего анализа} + +В данном разделе мы рассмотрим семейство алгоритмов нисходящего синтаксического (рекурсивный спуск, LL, GLL~\cite{Scott:2010:GP:1860132.1860320,10.1007/978-3-662-46663-6_5}) и их обобщение для задачи поиска путей с контекстно-свободными ограничениями. + +% и GLL~\cite{Grigorev:2017:CPQ:3166094.3166104} Другие реализации~\cite{MEDEIROS201975} + +\section{Рекурсивный спуск} + +Идея рекурсивного спуска основана на использовании программного стека вызовов в качестве стека магазинного автомата. Достигается это следующим образом. +\begin{itemize} + \item Для каждого нетерминала создаётся функция, принимающая ещё не обработанный остаток строки и возвращающая пару: результат вывода префикса данной строки из соответствующего нетерминала и не обработанный остаток строки. В случае распознавателя результат вывода --- логическое значение (выводится/не выводится). + \item Каждая такая функция реализовывает обработку цепочки согласно правым частям правил для соответствующих нетерминалов: считывание символа входа при обработке терминального символа, вызов соответствующей функции при обработке нетерминального. +\end{itemize} + +У такого подхода есть два ограничения: +\begin{enumerate} + \item Не работает с леворекурсивными грамматиками, то есть грамматиками, вывод в которых может принимать следующий вид: + $$ + S \to \cdots \to \underline{N_i} \alpha \to \cdots \underline{N_i} \beta \to \cdots \omega + $$ + \item Шаги должны быть однозначными. +\end{enumerate} + +\begin{example} + +Построим функцию рекурсивного спуска для продукции $S \rightarrow aSbS \mid \varepsilon$. + +\begin{algorithm} + \floatname{algorithm}{Listing} +\begin{algorithmic}[1] +\caption{Функция рекурсивного спуска} +\Function{S}{$\omega$} + \If {(len$(\omega)=0$)} + \Comment{{\footnotesize Пустая цепочка выводима из $S$}} + \State{\Return \textit{(true, $\omega$)}} + \EndIf + + \If{$(\omega = a :: tl)$} + \Comment{{\footnotesize Выводимая из $S$ подстрока должна начинаться с $a$}} + \State{$res,tl' = $ S($tl$)} + \Comment{{\footnotesize Затем должна идти подстрока, выводимая из $S$}} + \If{res \&\& $tl' = b :: tl''$} + \Comment{{\footnotesize Если вызов закончился успешно, то надо проверить, что следующий символ --- это $b$}} + \State{\Return $S(tl'')$} + \Comment{{\footnotesize И снова попробовать вывести перфикс из $S$}} + \Else + \State{\Return \textit{(false, $tl'$)}} + \EndIf + \Else + \State{\Return \textit{(false, $\omega$)}} + \EndIf +\EndFunction + +\end{algorithmic} +\end{algorithm} +\end{example} + +Если возвращаеммое значение этой функции --- пара вида \textit{(true, [])}, то разбор завершился успехом. + +Данный подход применяется как для ручного написания синтаксических нализаторов, так и при генерации анализаторов по грамматике. + +\section{LL(k)-алгоритм синтаксического анализа} + +LL(k) --- алгоритм синтаксического анализа --- нисходящий анализ без отката, но с предпросмотром. +Решение о том, какую продукцию применять, принимается на основании k следующих за текущим символом. +Временная сложность алгоритма $O(n)$, где $n$~--- длина слова. + +Алгоритм использует входной буфер, стек для хранения промежуточных данных и таблицу анализатора, которая управляет процессом разбора. +В ячейке таблицы указано правило, которое нужно применять, если рассматривается нетерминал $A$, а следующие $m$ символов строки~--- $t_{1} \dots t_{m}$, где $m \leq k$. +Также в таблице выделена отдельная колонка для $\$$~--- маркера конца строки. + +\begin{center} + \begin{tabular}{ c || c | c | c | c } + & $\dots$ & $t_{1} \dots t_{m}$ & $\dots$ & $\$$ \\ \hline + $\dots$ & $\dots$ & $\dots$ & $\dots$ & $\dots$ \\ \hline + $A$ & $\dots$ & $A \to \alpha$ & $\dots$ & $\dots$ \\ \hline + $\dots$ & $\dots$ & $\dots$ & $\dots$ & $\dots$ + \end{tabular} +\end{center} + +Для построения таблицы вычисляются множества $\first[k]$ и $\follow[k]$. Идейно их можно понимать, как первые или, соответственно, последующие $k$ символов в результирующем выводе, при использовании нетерминала $A$. Данную мысль хорошо иллюстрирует рисунок: + +\begin{center} + \begin{tikzpicture} + \draw[black, thick] (0,0) -- (2,4); + \draw[black, thick] (2,4) -- (4,0); + \draw[black, thick] (1,0) -- (2,2); + \draw[black, thick] (2,2) -- (3,0); + \draw[black, thick] (2,2) -- (3,0); + \draw[black, thick] (0,0) -- (1,0); + \draw[red, ultra thick] (1,0) -- (1.75,0); + \draw[black, thick] (1.75,0) -- (3,0); + \draw[red, ultra thick] (3,0) -- (3.75,0); + \draw[black, thick] (3.75,0) -- (4,0); + \filldraw[black] (2,4) circle (1pt) node[anchor=west] {S}; + \filldraw[black] (2,2) circle (1pt) node[anchor=west] {A}; + \filldraw[black] (0,0) circle (0pt) + node[anchor=east] {\textbf{$\omega$}}; + \filldraw[red] (1.5,0) circle (0pt) + node[anchor=north] {\footnotesize $\first[k](A)$}; + \filldraw[red] (3.75,0) circle (0pt) + node[anchor=north] {\footnotesize $\follow[k](A)$}; + \end{tikzpicture} +\end{center} + +Определим их формально: + +\begin{definition} + Пусть $G = \langle N, \Sigma, P, S \rangle$~--- КС-грамматика. Множество $\first[k]$ определено для сентенциальной формы $\alpha$ следующим образом: + \[ \first[k](\alpha) = \{ \omega \in \Sigma^* \mid \alpha \derives{} \omega \text{ и } |\omega| < k \text{ либо } \exists \beta: \alpha \derives{} \omega \beta \text{ и } |\omega| = k \} + \] + , где $\alpha, \beta \in (N \cup \Sigma)^*.$ +\end{definition} + +\begin{definition} + Пусть $G = \langle N, \Sigma, P, S \rangle$~--- КС-грамматика. Множество $\follow[k]$ определено для сентенциальной формы $\beta$ следующим образом: + \[\follow[k](\beta) = \{ \omega \in \Sigma^* \mid \exists \gamma, \alpha: S \derives{} \gamma \beta \alpha \text{ и } \omega \in \first[k](\alpha) \} \] +\end{definition} + +В частном случае для $k = 1$: + +\[ \first(\alpha) = \{ a \in \Sigma \mid \exists \gamma \in (N \cup \Sigma)^*: \alpha \derives{} a \gamma \} \text{, где } \alpha \in (N \cup \Sigma)^* \} \] + +\[ \follow(\beta) = \{ a \in \Sigma \mid \exists \gamma, \alpha \in (N \cup \Sigma)^* : S \derives{} \gamma \beta a \alpha \} \text{, где } \beta \in (N \cup \Sigma)^* \} \] + +Множество $\first$ можно вычислить, пользуясь следующими соотношениями: + +\begin{itemize} + \item $\first(a \alpha) = \{a\}, a \in \Sigma, \alpha \in (N \cup \Sigma)^* $ + \item $\first(\varepsilon) = \{\varepsilon\}$ + \item $\first(\alpha \beta) = \first(\alpha) \cup (\first(\beta) \text{, если } \varepsilon \in \first(\alpha))$ + \item $\first(A) = \first(\alpha) \cup \first(\beta) \text{, если в грамматике есть правила } A \to \alpha \mid\beta$ +\end{itemize} + +Алгоритм для вычисления множества $\follow$: + +\begin{itemize} + \item Положим $\follow(X) = \varnothing, \forall X \in N$ + \item $\follow(S) = \follow(S) \cup \{\$\} \text{, где } S \text{--- стартовый нетерминал}$ + \item Для всех правил вида $A \to \alpha X \beta: \follow(X) = \follow(X) \cup (\first(\beta) \setminus \{\varepsilon\} )$ + \item Для всех правил вида $A \to \alpha X \text{ и } A \to \alpha X \beta \text{, где } \varepsilon \in \first(\beta): \follow(X) = \follow(X) \cup \follow(A)$ + \item Последние два пункта применяются, пока есть что добавлять в строящиеся множества. +\end{itemize} + + +\begin{example} + +Рассмотрим грамматику $G$ со следующими продукциями: +\begin{align*} + S &\to a S' & A' \to b \mid a \\ + S' &\to A b B S' \mid \varepsilon & B \to c \mid \varepsilon\\ + A &\to a A' \mid \varepsilon +\end{align*} + + +Пример множеств $\first$ для нетерминалов грамматики $G$: + +\begin{multicols}{2} + +\columnbreak + +\begin{align*} + \first(S) &= \{ a \} & \first(B) &= \{ c, \varepsilon \} \\ + \first(A) &= \{ a, \varepsilon \} & \first(S') &= \{ a, b, \varepsilon \}\\ + \first(A') &= \{ a, b \} +\end{align*} +\end{multicols} + +Пример множеств $\follow$ для нетерминалов грамматики $G$: + +\begin{align*} + \follow(S) &= \{ \$ \} & \\ + \follow(S') &= \{ \$ \} &(S \to a S')\\ + \follow(A) &= \{ b \} &(S' \to A b B S') \\ + \follow(A') &= \{ b \} &(A \to a A')\\ + \follow(B) &= \{ a, b, \$ \} &(S' \to A b B S', \varepsilon \in \first(S')) +\end{align*} + +\end{example} + +Управляющая таблица LL(k) анализатора заполняется следующим образом: продукции $A \to \alpha, \alpha \neq \varepsilon$ помещаются в ячейки $(A, a)$, где $a \in \first(\alpha)$, продукции $A \to \alpha$~--- в ячейки $(A, a)$, где $a \in \follow(A)$, если $\varepsilon \in \first(\alpha)$ + +\begin{example} + +Пример таблицы для грамматики $S \to aSbS \mid \varepsilon$ + +\begin{center} +\begin{tabular}{ r || c | c || c | c | c } +N & $\first$ & $\follow$ & a & b & $\$ $ \\ \hline +$S$ & $\{ a, \varepsilon \}$ & $\{ b, \$ \}$ & $S \rightarrow aSbS$ & $S \rightarrow \varepsilon$ & $S \rightarrow \varepsilon$ +\end{tabular} +\end{center} + +\end{example} + +Однако, не для всех грамматик по множествам $\first[k]$ и $\follow[k]$ возможно выбрать применяемую продукцию, а значит, нельзя однозначно построить таблицу, необходимую для работы алгоритма, поэтому данный алгоритм применим только для грамматик особого класса --- LL(k). + +\begin{definition} + LL(k) грамматика --- грамматика, для которой на основании множеств $\first[k]$ и $\follow[k]$ можно однозначно определить, какую продукцию применять. +\end{definition} + +Важно заметить, что при больших $k$ управляющая таблица сильно разрастается, поэтому на практике данный алгоритм применим для небольших значений $k$. + +Интерпретатор автомата принимает входную строку и построенную управляющую таблицу и работает следующим образом. +В каждый момент времени конфигурация автомата это позиция во входной строке и стек. +В начальный момент времени стек пуст, а позиция во входной строке соответствует её началу. +На первом шаге в стек добавляются последовательно сперва символ конца строки, затем стартовый нетерминал. +На каждом шаге анализируется существующая конфигурация и совершается одно из действий. +\begin{itemize} +\item Если текущая позиция --- конец строки и вершина стека --- символ конца строки, то успешно завершаем разбор. +\item Если текущая вершина стека --- терминал, то проверяем, что позиция в строке соответствует этому терминалу. Если да, то снимаем элемент со стека, сдвигаем позицию на единицу и продолжаем разбор. Иначе завершаем разбор с ошибкой. +\item Если текущая вершина стека --- нетерминал $N_i$ и текущий входной символ $t_j$, то ищем в управляющей таблице ячейку с координатами $(N_i, t_j)$ и записываем на стек содержимое этой ячейки. +\end{itemize} + +\begin{example}Пример работы LL анализатора. +Рассмотрим грамматику $S \to aSbS \mid \varepsilon$ и выводимое слово $\omega = abab$. + +Расмотрим пошагово работу алгоритма, будем использовать таблицу, построенную в предыдущем примере: + +\begin{enumerate} + \item Начало работы. + + Стек: \, + \begin{tabular}[c]{ |c| } + \\ \hline + \$ \\ \hline + \end{tabular} + \qquad \qquad \qquad \qquad входное слово: \, + \begin{tabular}[c]{ |c|c|c|c|c| } + \hline + \textcolor{red}{a} & b & a & b & \$ \\ \hline + \end{tabular} + +Финальный символ лежит на стеке, а указатель указывает на первый символ слова. + + \item кладем стартовый символ на стек + + Стек: \, + \begin{tabular}[c]{ |c| } + \\ \hline + $S$ \\ \hline + \$ \\ \hline + \end{tabular} + \qquad \qquad \qquad \qquad входное слово: \, + \begin{tabular}[c]{ |c|c|c|c|c| } + \hline + \textcolor{red}{a} & b & a & b & \$ \\ \hline + \end{tabular} + + \item Ищем ячейку с координатами (S, a), применяем продукцию из ячейки. + + Стек: \, + \begin{tabular}[c]{ |c| } + \\ \hline + $a$ \\ \hline + $S$ \\ \hline + $b$ \\ \hline + $S$ \\ \hline + \$ \\ \hline + \end{tabular} + \qquad \qquad \qquad \qquad входное слово: \, + \begin{tabular}[c]{ |c|c|c|c|c| } + \hline + \textcolor{red}{a} & b & a & b & \$ \\ \hline + \end{tabular} + +\item Снимаем терминал $a$ со стека и двигаем указатель. + + Стек: \, + \begin{tabular}[c]{ |c| } + \\ \hline + $S$ \\ \hline + $b$ \\ \hline + $S$ \\ \hline + \$ \\ \hline + \end{tabular} + \qquad \qquad \qquad \qquad входное слово: \, + \begin{tabular}[c]{ |c|c|c|c|c| } + \hline + a & \textcolor{red}{b} & a & b & \$ \\ \hline + \end{tabular} + +\item Ищем ячейку с координатами (S, b), применяем продукцию из ячейки. + + Стек: \, + \begin{tabular}[c]{ |c| } + \\ \hline + $b$ \\ \hline + $S$ \\ \hline + \$ \\ \hline + \end{tabular} + \qquad \qquad \qquad \qquad входное слово: \, + \begin{tabular}[c]{ |c|c|c|c|c| } + \hline + a & \textcolor{red}{b} & a & b & \$ \\ \hline + \end{tabular} + +\item Снимаем терминал $b$ со стека и двигаем указатель. + + Стек: \, + \begin{tabular}[c]{ |c| } + \\ \hline + $S$ \\ \hline + \$ \\ \hline + \end{tabular} + \qquad \qquad \qquad \qquad входное слово: \, + \begin{tabular}[c]{ |c|c|c|c|c| } + \hline + a & b & \textcolor{red}{a} & b & \$ \\ \hline + \end{tabular} + + \item Ищем ячейку с координатами (S, a), применяем продукцию из ячейки. + + Стек: \, + \begin{tabular}[c]{ |c| } + \\ \hline + $a$ \\ \hline + $S$ \\ \hline + $b$ \\ \hline + $S$ \\ \hline + \$ \\ \hline + \end{tabular} + \qquad \qquad \qquad \qquad входное слово: \, + \begin{tabular}[c]{ |c|c|c|c|c| } + \hline + a & b & \textcolor{red}{a} & b & \$ \\ \hline + \end{tabular} + +\item Снимаем терминал $a$ со стека и двигаем указатель. + + Стек: \, + \begin{tabular}[c]{ |c| } + \\ \hline + $S$ \\ \hline + $b$ \\ \hline + $S$ \\ \hline + \$ \\ \hline + \end{tabular} + \qquad \qquad \qquad \qquad входное слово: \, + \begin{tabular}[c]{ |c|c|c|c|c| } + \hline + a & b & a & \textcolor{red}{b} & \$ \\ \hline + \end{tabular} + +\item Ищем ячейку с координатами (S, b), применяем продукцию из ячейки. + + Стек: \, + \begin{tabular}[c]{ |c| } + \\ \hline + $b$ \\ \hline + $S$ \\ \hline + \$ \\ \hline + \end{tabular} + \qquad \qquad \qquad \qquad входное слово: \, + \begin{tabular}[c]{ |c|c|c|c|c| } + \hline + a & b & a & \textcolor{red}{b} & \$ \\ \hline + \end{tabular} + +\item Снимаем терминал $b$ со стека и двигаем указатель. + + Стек: \, + \begin{tabular}[c]{ |c| } + \\ \hline + $S$ \\ \hline + \$ \\ \hline + \end{tabular} + \qquad \qquad \qquad \qquad входное слово: \, + \begin{tabular}[c]{ |c|c|c|c|c| } + \hline + a & b & a & b & \textcolor{red}{\$} \\ \hline + \end{tabular} + +\item Ищем ячейку с координатами (S, \$), применяем продукцию из ячейки. + + Стек: \, + \begin{tabular}[c]{ |c| } + \\ \hline + \$ \\ \hline + \end{tabular} + \qquad \qquad \qquad \qquad входное слово: \, + \begin{tabular}[c]{ |c|c|c|c|c| } + \hline + a & b & a & b & \textcolor{red}{\$} \\ \hline + \end{tabular} + +\item Оказались в конце строки и на вершине стека символ конца --- завершаем разбор. + +\end{enumerate} + +\end{example} + +Можно расширить данный алгоритм так, чтобы он строил дерево вывода. Дерево будет строиться сверху вниз, от корня к листьям. Для этого необходимо расширить шаги алгоритма. +\begin{itemize} + \item В ситуации, когда мы читаем очередной терминал (на вершине стека и во входе одинаковые терминалы), мы создаём лист с соответствующим терминалом. + \item В ситуации, когда мы заменяем нетерминал на стеке на правую часть продукции в соответствии с управляющей таблицей, мы создаём нетерминальный узел соответствующий применяемой продукции. +\end{itemize} + +Данное семейство алгоритмов всё так же не работает с леворекурсивными грамматиками и с неоднозначными грамматиками. + +Таким образом, по некоторым грамматикам можно построить LL(k) анализатор (назовём их LL(k) грамматиками), но не по всем. +С левой рекурсией, конечно, можно бороться, так как существуют алгоритмы устранения левой и скрытой левой рекурсии, а вот с неоднозначностями ничего не поделаешь. + + + +\section{Алгоритм Generalized LL} + +Можно построить анализатор, работающий с произвольными КС-грамматиками. +Generalized LL (GLL)~\cite{Scott:2010:GP:1860132.1860320,10.1007/978-3-662-46663-6_5} + +Обзор:~\cite{Cappers2014ExploringAV}, история и т.д.~\cite{Afroozeh2019PracticalGT} + +Принцип работы остается абсолютно таким же, как для табличного LL: +\begin{itemize} + \item Сначала по грамматике строится \textit{управляющая} таблица + \item Затем построенная таблица команд и непосредственно анализируемое слово поступают на вход абстрактному интерпретатору. + \item Для своей работы интерпретатор поддерживает некоторую вспомогательную структуру данных (стек для LL). + \item Один шаг разбора состоит в том, чтобы рассмотреть текущую позицию в слове, применить все соответствующие ей правила из таблицы и при возможности сдвинуть позицию разбора вправо. +\end{itemize} + +Где в этой схеме возникают ограничения на вид обрабатываемой грамматики для алгоритма LL? На самом первом шаге --- при построении таблицы может возникнуть ситуация, когда одному нетерминалу $N_j$ и последовательности $first_k(N_j)$ соответствует несколько продукций грамматики. В этом случае грамматика признавалась не соответствующей классу LL(k) и отвергалась анализатором. + +Теперь же мы разрешим такую ситуацию и в этом случае в ячейку таблицы будем записывать все продукции грамматики, соответствующие этой ячейке. Однако сразу же возникает вопрос --- а что делать интерпретатору, когда при разборе ему необходимо применить правило, состоящее из нескольких продукций? Общий ответ такой --- необходим некоторый вид недетерминизма, при котором интерпретатор мог бы ``параллельно'' обрабатывать несколько возможных вариантов синтаксического разбора. + +Эти два свойства (модифицированная управляющая таблица и недетерминизм) суть главные принципиальные отличия GLL(k) от LL(k). Далее мы перейдем к рассмотрению непосредственно технической реализации описанного алгоритма. + +Нам необходимо научиться задавать различные ветви (пути) синтаксического разбора и переключаться между ними. Заметим, что состояние любой ветви в любой момент времени суть следующее: необходимо распознать символ $N_j \in N \cup \Sigma$ из продукции $X$, начиная с элемента слова под индексом $i$. Т.е. имеем позицию в слове и позицию символа в продукции. Последнее принято называть \textit{слотом грамматики}. + +\begin{definition} + Пусть $G = \langle N, \Sigma, P, S \rangle$~--- КС-грамматика. \textit{Слотом грамматики} $G$ (позицией грамматики $G$) назовем пару из продукции $X \in P$ и позиции $0 \leq q \leq length(body(X))$ тела продукции $X$. При этом введем следующее обозначение $X ::= \alpha \cdot \beta, \quad \alpha,\beta \in (N \cup \Sigma)^*$, где $ \cdot $ указывает на позицию в продукции. +\end{definition} + +Описанная пара позиций уже однозначно задает состояние синтаксического разбора. Имеем множество состояний и переходов между ними --- возникает естественное желание воспользоваться терминами графов для представления этой структуры. Такую конструкцию называют \textit{граф-структурированный стек} или \textit{GSS} (Graph Structured Stack), который впервые был предложен Масару Томитой ~\cite{tomita1988graph} в контексте восходящего анализа. GSS будет являться рабочей структурой нашего нового интерпретатора вместо стека для LL. Состояние разбора вместе с узлом GSS мы будет называть \textit{дескриптором}. + +\begin{definition} + Пусть $G = \langle N, \Sigma, P, S \rangle$~--- КС-грамматика, $X$~--- слот грамматики $G$, $i$~--- позиция в слове $ w $ над алфавитом $\Sigma$, а $ u $~--- узел GSS. \textit{Дескриптором} назовём тройку $ (X, u, i) $. +\end{definition} + +Есть несколько способов задания GSS для алгоритма GLL. Вариант, предложенный самими авторами алгоритма, оперирует непосредственно парами из позиции слова и слота грамматики в качестве состояний (и узлов графа). Такой метод является довольно простым и наглядным, но, как описано в работе \cite{10.1007/978-3-662-46663-6_5}, не самым эффективным. Предложим сразу чуть более оптимальное представление: заметим, что шаги разбора, соответствующие одному и тому же нетерминалу и позиции слова, должны выдавать один и тот же результат независимо от конкретной продукции грамматики, в которой стоит этот нетерминал. Поэтому заводить по узлу на каждый слот грамматики довольно избыточно --- вместо этого в качестве состояния будем использовать пары из нетерминала и позиции слова, а позиции грамматики будем записывать на рёбрах. + +Итак, мы научились задавать состояния с помощью дескрипторов, а также определились со вспомогательной структурой GSS. Теперь можно перейти к рассмотрению непосредственно самого алгоритма, суть которого довольно проста и напоминает BFS по неявному графу. + +Дескриптор задает состояние, которое необходимо обработать. При этом мы без какой-либо дополнительной информации можем продолжить анализ входа из состояния, задаваемого этим дескриптором. В процессе обработки мы можем получить несколько новых состояний. Поэтому будем поддерживать множество $ R $ дескрипторов на обработку --- на каждом шаге извлекаем один из множества, проводим анализ и добавляем во множество новые полученные. + +При каких условиях этот процесс будет конечен? Ну, например, если мы каждое состояние будем обрабатывать не более одного раза. И действительно, поскольку наш интерпретатор является ``чистым'' в том смысле, что для одного и того же состояния каждый раз будут получены одинаковые результаты, проводить анализ дважды не имеет смысла. Поэтому будем также поддерживать множество $ U $ всех полученных в ходе разбора дескрипторов, и добавлять в $ R $ только те, которых еще нет в $ U $. + +И наконец, заключительная и самая главная часть --- как происходит обработка дескриптора? +Пусть дескриптор имеет вид $ (X, u, i) $, а входное слово обозначим $ W $. Есть три возможных варианта, в зависимости от вида позиции грамматики $ X $ --- разберем каждый из них по отдельности; + +\begin{itemize} + \item $ X ::= \alpha \cdot t \beta $, т.е. указатель смотрит на терминал --- в этом случае новых дескрипторов добавлено не будет. Если $ W[i] = t $, то мы сдвигаем указатель слота, переходя к рассмотрению $ X ::= \alpha t \cdot \beta $, и инкрементируем позицию $ i $ в слове. В противном же случае сразу переходим к следующему дескриптору, таким образом терминируя текущую ветвь разбора. + + \item $ X ::= \alpha \cdot A \beta $, т.е. указатель смотрит на нетерминал. Нам нужен GSS узел $ v $ вида $ (A, i) $ и ребро $ (u, X ::= \alpha A \cdot \beta, v) $ (ребро из $ u $ в $ v $ с пометкой $ X ::= \alpha A \cdot \beta $). Если такой узел и ребро уже существуют в нашем GSS, берем их, иначе --- создаём. Далее в $ R $ добавляем по дескриптору для узла $ v $ и каждого правила грамматики из ячейки управляющей таблицы для нетерминала $ A $ (конечно, если их еще не было в $ U $). На этом обработка текущего дескриптора завершается. + + \item $ X ::= \alpha \cdot $, т.е. указатель находится в конце продукции. Продукция разобрана, а значит, интерпретатору необходимо вернуться из разбора $ X $ к вызывающему правилу и продолжить разбор там (это, в некотором смысле, соответствует возврату из функции разбора нетерминала в методе рекурсивного спуска). По каждому исходящему ребру $ (u, Y, v) $ добавляем (если уже не существует) дескриптор $(Y, v, i)$. +\end{itemize} + +Результатом синтаксического разбора является успех тогда и только тогда, когда был достигнут дескриптор вида $ (S ::= \alpha \cdot, s, n) $, где слот грамматики представляет собой любое правило для аксиомы $ S $, узел GSS $ s $ состоит из аксиомы $ S $ и 0, а позиция входного слова равна его длине $ n $. Если же после разбора всех полученных дескрипторов указанный найден не был, результатом будет являться провал. + +Давайте посмотрим, как такой алгоритм справится с неоднозачной грамматикой с леворекурсивным правилом. + +\begin{example} + \label{gll:example1} + Пусть грамматика $ G $ имеет вид $ S \to SSS \mid SS \mid a $, а разбираемое слово $ w = aaa $. Тогда GSS, соответствующий разбору $S \Rightarrow SSS \Rightarrow aSS \Rightarrow aaS \Rightarrow aaa$, будет выглядеть следующим образом (для удобства каждое ребро дополнительно пронумеровано): + + \begin{center} + \input{figures/gll/complete.tex} + \end{center} + + Далее мы пошагово рассмотрим процесс его построения, а пока отметим несколько особенностей: + + \begin{itemize} + \item Это \textit{неполный} GSS. Для задачи синтаксического анализа такого достаточно, поскольку если в какой-то момент был достигнут финальный дескриптор, то обрабатывать все последующие уже не нужно. Однако, для задачи построения SPPF, как мы отметим далее, это уже не так, поскольку она требует агрегирования всех возможных путей разбора. + + \item Обратите особое внимание на наличие петель. Они как раз-таки и обеспечивают эффективную работу с леворекурсивными правилами, поскольку переиспользуются уже существующие узлы. При этом кратных петель, понятно, не создается, т.к. мы запоминаем все достигнутые дескрипторы в множестве $ U $ и дублирующих дескрипторов в рабочее множество $ R $ не добавляем. + + \item В GSS не создаются узлы, соответствующие разбору терминалов (например, $a, 0$). В действительности так можно было бы сделать. Но тогда при обработке слота, указывающего на терминал, сначала бы создался узел GSS, затем интерпретатор сверил бы терминал и символ в слове, после чего, если они совпали, произошел бы возврат из узла, а если нет, узел был бы отброшен и интерпретатор перешел бы к другому дескриптору. Таким образом, при любом случае сначала создается узел, затем выполняется проверка, после чего узел сразу отбрасывается. Для того, чтобы не создавать такие ``одноразовые'' узлы, проверка терминалов выполняется in-place. + \end{itemize} + + Пронумеруем продукции и выпишем управляющую таблицу: + + \begin{table}[!htb] + \begin{minipage}{.5\linewidth} + \centering + \begin{tabular}{lc} + $S \to S S S$ & (0) \\ + $S \to S S$ & (1) \\ + $S \to a$ & (2) + \end{tabular} + \end{minipage}% + \begin{minipage}{.5\linewidth} + \centering + \begin{tabular}{ r || c || c | c} + N & $\first$ & a & $\$ $ \\ \hline + $S$ & $\{ a \}$ & 0,1,2 & + \end{tabular} + \end{minipage} + \end{table} + + Разумеется, что конкретный порядок исполнения алгоритма будет зависеть, например, от используемой в качестве рабочего множества $ R $ структуры данных и от порядка обработки правил из ячейки управляющей таблицы. Рассмотрим лишь один из возможных вариантов: + + \begin{enumerate} + \item Для начала мы создаем узел GSS $ s_0 = (S, 0) $ и дескрипторы для правил из ячейки таблицы $ S, a $: $ (S \to \cdot SSS, s_0, 0), (S \to \cdot SS, s_0, 0), (S \to \cdot a, s_0, 0) $. + + \begin{center} + \input{figures/gll/state0.tex} + \end{center} + + \item При обработке $ (S \to \cdot S S S, s_0, 0) $ образовываются петля 1 и дескрипторы \linebreak $ (S \to \cdot SSS, s_0, 0), (S \to \cdot SS, s_0, 0), (S \to \cdot a, s_0, 0) $, которые уже содержатся в множестве $ U $ после шага 1 и поэтому не добавляются повторно. + + \begin{center} + \input{figures/gll/state1.tex} + \end{center} + + \item При обработке $ (S \to \cdot S S, s_0, 0) $ образовывается петля 2, а в остальном аналогично \mbox{шагу 2.} + + \begin{center} + \input{figures/gll/state2.tex} + \end{center} + + \item При обработке $ (S \to \cdot a, s_0, 0) $ мы распознаем терминал $a$ на позиции 0 и, возвращаясь по петлям 1 и 2, добавляем дескрипторы $ (S \to S \cdot S S, s_0, 1), (S \to S \cdot S, s_0, 1) $. + + \item При обработке $ (S \to S \cdot S S, s_0, 1) $ образовываем узел $s_1 = (S, 1)$ с исходящим ребром 3 и добавляем дескрипторы $ (S \to \cdot SSS, s_1, 1), (S \to \cdot SS, s_1, 1), (S \to \cdot a, s_1, 1) $. + + \begin{center} + \input{figures/gll/state3.tex} + \end{center} + + \item При обработке $ (S \to S \cdot S, s_0, 1) $ образовываем ребро 4, новых дескрипторов не добавляется. + + \begin{center} + \input{figures/gll/state4.tex} + \end{center} + + \item Обработка дескриптора $ (S \to \cdot S S S, s_1, 1) $ аналогична шагу 2 с добавлением петли 5. + + \begin{center} + \input{figures/gll/state5.tex} + \end{center} + + \item Обработка дескриптора $ (S \to \cdot S S, s_1, 1) $ аналогична шагу 3 с добавлением петли 6. + + \begin{center} + \input{figures/gll/state6.tex} + \end{center} + + \item При обработке $ (S \to \cdot a, s_1, 1) $ мы распознаем терминал $a$ на позиции 1 и, возвращаясь по ребрам 3 и 4, добавляем дескрипторы $ (S \to S S \cdot S, s_0, 2), (S \to S S \cdot, s_0, 2) $, а также, возвращаясь по петлям 5 и 6, добавляем дескрипторы $ (S \to S \cdot S S, s_1, 2), (S \to S \cdot S, s_1, 2) $. + + \item При обработке $ (S \to S S \cdot S, s_0, 2) $ образовываем узел $s_2 = (S, 2)$ с исходящим ребром 7 и добавляем дескрипторы $ (S \to \cdot SSS, s_2, 2), (S \to \cdot SS, s_2, 2), (S \to \cdot a, s_2, 2) $. + + \begin{center} + \input{figures/gll/state7.tex} + \end{center} + + \item Обработка дескриптора $ (S \to \cdot S S S, s_2, 2) $ аналогична шагу 2 с добавлением петли 8. + + \begin{center} + \input{figures/gll/state8.tex} + \end{center} + + \item Обработка дескриптора $ (S \to \cdot S S, s_2, 2) $ аналогична шагу 3 с добавлением петли 9. + + \begin{center} + \input{figures/gll/complete.tex} + \end{center} + + \item При обработке $ (S \to \cdot a, s_2, 2) $ мы распознаем терминал $a$ на позиции 2 и, возвращаясь по ребру 7, добавляем дескриптор $ (S \to S S S \cdot, s_0, 3) $, а также, возвращаясь по петлям 8 и 9, добавляем дескрипторы $ (S \to S \cdot S S, s_2, 3), (S \to S \cdot S, s_2, 3) $. + + \item Мы достигли финального дескриптора $ (S \to S S S \cdot, s_0, 3) $, синтаксический разбор успешен. + \end{enumerate} + +\end{example} + +Внимательный читатель мог заметить, что если бы в этом примере шаг 4 был выполнен перед шагом 2, разбор довольно быстро бы завершился неудачей. Отсюда вытекает следующее наблюдение: если в какой-то момент из существующего узла появилось новое ребро, необходимо пересчитать все входящие в него пути. + +Для построения SPPF требуется внести лишь несколько небольших добавлений: + +\begin{enumerate} + \item В дескриптор необходимо добавить узел SPPF $ w $, который будет представлять уже разобранный префикс. + \item Необходимо поддерживать множество $ P $ из элементов вида $ (u, z) $, где $ u $ это узел GSS, а $ z $ соответствующий ему узел SPPF, для того, чтобы переиспользовать результаты разбора, ассоциированные с узлами GSS. + \item При обработке терминала $ t $ на позиции $ i $ ищется узел вида $ (t, i, i + 1) $, либо создается, если такого еще нет. + \item При обработке нетерминала с помощью $ P $ ищется или при необходимости создается промежуточный узел вида $ (X, l, r) $, где $ X $ соответствующий слот грамматики, а $ l $ и $ r $ узлы SPPF, отвечающие за разбор левой и правой частей слота соответственно. +\end{enumerate} + +Конкретные шаги построения SPPF будут зависеть от выбранного для него формата. Описание эффективного бинаризованного SPPF и детали его построения при выполнении GLL представлены в работе~\cite{10.1007/978-3-662-46663-6_5}. + + \section{Алгоритм вычисления КС запросов на основе GLL} + +GLL довольно естественно обобщается на граф~\cite{Grigorev:2017:CPQ:3166094.3166104}: позициями входа теперь будем считать не индексы линейного слова, а вершины графа. В самом же алгоритме требуется внести лишь два небольших дополнения: + +\begin{enumerate} + \item Теперь при обработке терминала ``следующих'' символов может быть несколько --- рассматриваем каждый из них отдельно, сдвигаясь по соответствующему ребру. В результате, при одном чтении можем получить несколько новых дескрипторов, но они независимы, потому просто ставим их в рабочее множество $ R $. + \item При обработке нетерминала, аналогично, правила управляющей таблицы применяются для каждого из ``следующих'' символов в графе. Соответственно новых дескрипторов будет сгенерировано больше, но все они по-прежнему независимы и просто добавляются в рабочее множество $ R $. +\end{enumerate} + +Подробное описание алгоритма и псевдокод представлены в работе~\cite{Grigorev:2017:CPQ:3166094.3166104}. Существует ещё одно обобщение нисходящего синтаксического анализа для решения задачи КС достижимости~\cite{MEDEIROS201975}, которое предполагает непосредственное обобщение LL(k) алгоритма, что приводит к аналогичному результату, однако теряется связь с некоторыми построениями. + +Основанный на нисходящем анализе алгоритма поиска путей с контекстно-свободными ограничениями имеет следующие особенности. +\begin{enumerate} + \item Необходимо явно задавать начальную вершину, поэтому хорошо подходит для задач поиска путей с одним источником (single-source) или с небольшим количеством источников. Для поиска путей между всеми парами вершин необходимо явным образом все указать стартовыми. + \item Является направленным сверху вниз --- обходит граф последовательно начиная с указанной стартовой вершины и строит вывод, начиная со стартового нетерминала. Как следствие, в отличие от алгоритмов на основе линейной алгебры и Хеллингса, обойдёт только подграф, необходимый для построения ответа. В среднем это меньше, чем весь граф, который обрабатывается другими алгоритмами. + \item Естественным образом строит множество путей в виде сжатого леса разбора. + \item Использует существенно более тяжеловесные стуктуры данных и плохо распараллеливается (на практике). Как следствие, при решении задачи достижимости для всех пар путей проигрывает алгоритмам на основе линейной алгебры. +\end{enumerate} + +Частным случаем применения задачи КС достижимости является синтаксический анализ с неоднозначной токенизацией, то есть ситуацией, когда несколько пересекающихся подстрок во входной строке символов могут задавать разные лексические единицы и не возможно сделать однозначный выбор на этапе лексического анализа. +Например, для строки \verb|x = a---b| возможны несколько вариантов токенизации. +\begin{enumerate} + \item \verb|ID(x) OP_EQ ID(a) OP_MINUS OP_DECRIMENT ID(b)| + %\item \verb|ID(x) OP_EQ ID(A) OP_MINUS OP_UN_MINUS ID(b)| + \item \verb|ID(x) OP_EQ ID(a) OP_DECRIMENT OP_MINUS ID(b)| +\end{enumerate} + +В таком случае на вход синтаксическому анализатору можно подать DAG, содержащий все возможные варианты токенизации. Для нашего примера он может выглядеть следующим образом: + +\begin{center} + \begin{tikzpicture}[node distance=4cm,shorten >=1pt,on grid,auto] + \node[state] (q_0) at (0,0) {$0$}; + \node[state] (q_1) at (2.5,0) {$1$}; + \node[state] (q_2) at (5.5,0) {$2$}; + \node[state] (q_3) at (8,0) {$3$}; + \node[state] (q_4) at (10,-2) {$4$}; + \node[state] (q_5) at (11.5,0) {$6$}; + \node[state] (q_6) at (10,2) {$5$}; + \node[state] (q_7) at (14,0) {$7$}; + \path[->] + (q_0) edge node {ID(x)} (q_1) + (q_1) edge node {OP\_EQ} (q_2) + (q_2) edge node {ID(a)} (q_3) + (q_3) edge[left] node {OP\_MINUS} (q_4) + (q_4) edge[right] node {OP\_DECRIMENT} (q_5) + (q_3) edge node {OP\_DECRIMENT} (q_6) + (q_6) edge node {OP\_MINUS} (q_5) + (q_5) edge node {ID(b)} (q_7); + \end{tikzpicture} +\end{center} + +Далее будем проверять наличие пути из старовой (нулевой) вершины в конечную (соответствующую концу строки). Если таких путей оказалось несколько, то нужны дополнительные средства для выбора нужного дерева разбора. Данная идея рассматривается в работе~\cite{10.1145/3357766.3359532}. + +Напоследок сделаем небольшое замечание об эффективной реализации: в качестве рабочего множества $ R $ можно использовать несколько различных структур данных и, как правило, выбирают очередь. Однако иногда (в особенности для графов) лучше использовать стек дескрипторов, так как в этом случае выше локальность данных --- мы кладём пачку дескрипторов, соответствующих исходящим рёбрам. И если граф представлен списком смежности, то исходящие будут храниться рядом и их лучше обработать сразу. + +%\section{Вопросы и задачи} +%\begin{enumerate} +% \item Проведите алгоритм GLL для грамматики $ S \to a S b S \mid \varepsilon$. Правда ли, что эта грамматика принадлежит классу $ LL(1) $? Пронаблюдайте, как использование GSS вырождается в работу с обычным стеком. +% \item Доразберите все не рассмотренные в примере \ref{gll:example1} дескрипторы, постройте полный GSS. +%\end{enumerate} + diff --git a/tex/GLR-based_CFPQ.tex b/tex/GLR-based_CFPQ.tex new file mode 100644 index 0000000..6d67bf8 --- /dev/null +++ b/tex/GLR-based_CFPQ.tex @@ -0,0 +1,1159 @@ +\chapter{Алгоритм на основе восходящего анализа}\label{chpt:GLR} + +В данном разделе будут рассмотрены алгоритмы восходящего синтаксического анализа LR-семейства, в том числе Generalized LR (GLR). Также будет рассмотрено обобщение алгоритма GLR для решения задачи поиска путей с контекстно-свободными ограничениями в графах. + +\section{Восходящий синтаксический анализ} + +Существует большое семейство LR(k) алгоритмов --- алгоритм восходящего синтаксического анализа. +Основная идея, лежащая в основе семейства, заключается в следующем: входная последовательность символов считывается слева направо с попутным добавлением в стек и выполнением сворачивания на стеке --- замены последовательности терминалов и нетерминалов, лежащих наверху стека, на нетерминал, если существует соответствующее правило в исходной грамматике. + +Как и в случае с LL, используется магазинный автомат, управляемый таблицами, построенными по грамматике. +При этом, у LR анализатора есть два типа команд: +\begin{enumerate} + \item shift --- прочитать следующий символ входной последовательности, положив его в стек, и перейти в следующее состояние; + \item reduce(k) --- применить k-ое правило грамматики, правая часть которого уже лежит на стеке: снимаем со стека правую часть продукции и кладём левую часть. +\end{enumerate} + +А управляющая таблица выглядит следующим образом. + +\begin{center} + \begin{tabular}{c||c|c|c|c|c||c|c|c|c} + States & $t_0$ &$\dots$ & $t_a$ & $\dots$ & \$ & $N_0$ &$\dots$ & $N_b$ & $\dots$ \\ \hline \hline + $\dots$ & $\dots$ &$\dots$ & $\dots$ & $\dots$ & $\dots$ & $\dots$ &$\dots$ & $\dots$ & $\dots$ \\ \hline + $10$ & $\dots$ &$\dots$ & $s_i$ & $\dots$ & $r_k$ & $\dots$ &$\dots$ & $j$ & $\dots$ \\ \hline + $\dots$ & $\dots$ &$\dots$ & $\dots$ & $\dots$ & $acc$ & $\dots$ &$\dots$ & $\dots$ & $\dots$ + \end{tabular} +\end{center} + +Здесь +\begin{itemize} + \item $s_i$~--- shift: перенести соответствующи символ в стек и перейти в состояние $i$. + \item $r_k$~--- reduce(k): в стеке накопилась правая часть продукции $k$, пора производить свёртку. + \item $j$~--- goto: выполняется после reduce. Сама по себе команда reduce не переводит автомат в новое состояние. Команда goto переведёт автомат в состояние $j$. + \item $acc$~--- accept: разбор завершился успешно. +\end{itemize} + +Если ячейка пустая и в процессе работы мы пропали в неё --- значит произошла ошибка. Для детерминированной работы анализатора требуется, чтобы в каждой ячейке было не более одной команды. Есди это не так, то говорят о возникновении конфликтов. + +\begin{itemize} +\item shift-reduce --- ситуация, когда не понятно, читать ли следующий символ или выполнить свёртку. Например, если правая часть одного из правил является префиксом правой части другого правила: $N \rightarrow w, M \rightarrow ww'$. +\item reduce-reduce --- ситуация, когда не понятно, к какому правилу нужно применить свёртку. +Например, если есть два правила с одинаковыми правыми частями: $N \rightarrow w, M \rightarrow w$. +\end{itemize} + +Принцип работы LR анализаторов следующий. Пусть у нас есть входная строка, LR-автомат со стеком и управляющая таблица. +В начальный момент на стеке лежит стартовое состояние LR-автомата, позиция во входной строке соответствует её началу. +На каждом шаге анализируется текущий символ входа и текущее состояние, в котором находится автомат, и совершается одно из действий: +\begin{itemize} +\item Если в управляющей таблице нет инструкции для текущего состояния автомата и текущего символа на входе, то завершаем разбор с ошибкой. +\item Иначе выполняем одну из инструкций: +\begin{itemize} +\item в случае acc --- успешно завершаем разбор. +\item в случае shift --- кладем на стек текущий символ входа, сдвигая при этом текущую позицию, и номер нового состояния. Переходим в новое состояние. +\item в случае reduce(k) --- снимаем со стека 2l элементов: l состояний и l терминалов/нетерминалов (где l --- длина правой части k-ого правила), кладём на стек нетерминал левой части правила. Тперь на вершине стека у нас нетерминал $N_a$, а следующий элемент --- состяние $i$. Если в ячейке $(i,N_a)$ управляющей таблицы лежит состояние $j$, то кладём его на вершину стека. Иначе завершаемся с ошибкой. +\end{itemize} +\end{itemize} + + +Разные алгоритмы из LR-семейства строят таблицы разными способами и, соответственно, могут избегать тех или иных конфликтов. Рассмотрим некоторых представителей. + +\subsection{LR(0) алгоритм} + +Данный алгоритм самый ``слабый'' из семейства: разбирает наименьший класс языков. +Для построения используются LR(0) пункты. + +\begin{definition} +LR(0) пункт (LR(0) item) --- правило грамматики, в правой части которого имеется точка, отделяющая уже разобранную часть правила (слева от точки) от того, что еще предстоит распознать (справа от точки): $A \to \alpha \cdot \beta$, где $A \to \alpha \beta$~--- правило грамматики. +\qed +\end{definition} + +Состояние LR(0) автомата --- множество LR(0) пунктов. Для их построения используется операция \textit{closure} или \textit{замыкание}. + +\begin{definition} +$closure(X) = closure(X \cup \{M \rightarrow \cdot \gamma \mid N_i \rightarrow \alpha\cdot M\beta \in X \})$ +\qed +\end{definition} + +\begin{definition} +Ядро --- исходное множество пунктов, до применения к нему замыкания. +\qed +\end{definition} + +Для перемещения точки в пункте используется функция \textit{goto}. + +\begin{definition} +$goto(X,p) = \{N_j \rightarrow \alpha p \cdot \beta \mid N_j \rightarrow \alpha\cdot p\beta \in X \}$ +\qed +\end{definition} + +Теперь мы можем построить LR(0) автомат. +Первым шагом необходимо расширить грамматику: добавить к исходной грамматике правило вида $S' \to S \$$, где $S$ --- стартовый нетерминал исходной грамматики, $S'$ --- новый стартовый нетерминал (не использовался ранее в грамматике), $\$$ --- маркер конца строки (не входил в терминальный алфавит исходной грамматики). + +Далее строим автомат по следующим принципам. + +\begin{itemize} + \item Состояния~--- множества пунктов. + \item Переходы между состяниями осуществляются по символам грамматики. + \item Начальное состояние~--- $closure(\{S'\to + \cdot S \$\})$. + \item Следующее состояние по текущему состоянию $X$ и смволу $p$ вычисляются как $closure(goto(X, p))$ + \end{itemize} + +Управляющая таблица по автомату строится следующим образом. + +\begin{itemize} + \item $acc$ в ячейку, соответствующую финальному состоянию и \$ + \item $s_i$ в ячейку $(j,t)$, если в автомате есть переход из состояния $j$ по терминалу $t$ в состояние $i$ + \item $i$ в ячейку $(j, N)$, если в автомате есть переход из состояния $j$ по нетерминалу $N$ в состояние $i$ + \item $r_k$ в ячейку $(j,t)$, если в состоянии $j$ есть пункт $A \to \alpha \cdot$, где $A \to \alpha$~--- $k$-ое правило грамматики, $t$~--- терминал грамматики + \end{itemize} + +\subsection{SLR(1) алгоритм} + +SLR(1) анализатор отличается от LR(0) анализатора построением таблицы по автомату (автомат в точности, как у LR(0). +А именно, $r_k$ добавляется в ячейку $(j,t)$, если в состоянии $j$ есть пункт $A \to \alpha \cdot$, где $A \to \alpha$~--- $k$-ое правило грамматики, $t \in FOLLOW(A)$ + +\subsection{CLR(1) алгоритм} + +Canonical LR(1), он же LR(1). +Данный алгоритм является дальнейшим расширением SLR(1): к пунктам добавляются множества предпросмотра (lookahead). + +\begin{definition} +Множество предпросмотра для правила $P$ --- терминалы, которые должны встретиться в выведенной строке сразу после строки, выводимой из данного правила. +\qed +\end{definition} + +\begin{definition} +CLR пункт: $ [A \to \alpha \cdot \beta, \{ t_0, \dots, t_n\}] $, +где $t_0, \dots, t_n$ --- множество предпросмотра для правила $A \to \alpha \beta$. +\qed +\end{definition} + + +\begin{definition} +Пусть дана грамматика $G = \langle \Sigma, N, R, S\rangle$. +\begin{align*} + closure(X) = closure(X \cup \{&[B \to \cdot \delta, \{FIRST(\beta t_0), \dots, FIRST(\beta t_n)\}] \\ + &\mid B \to \beta \in R, [A \to \alpha \cdot B \beta, \{t_0, \dots, t_n\}] \in closure(X)\}) +\end{align*} +\qed +\end{definition} + +Функция \textit{goto} определяется аналогично LR(0), автомат строится по тем же принципам. + +При построении управляющей таблицы усиливается правило добавлеия команды \textit{redice}. +А именно, добавляем $r_k$ в ячейку $(j,t_i)$, если в состоянии $j$ есть пункт $[A \to \alpha \cdot, \{t_0, \dots, t_n\}]$, где $A \to \alpha$~--- $k$-ое правило грамматики. + +\subsection{Примеры} + +Рассмотрим построение автоматов и таблиц для различных модификаций LR алгоритма. + +Возьмем следующую грамматику: +\begin{align*} +0) S & \rightarrow a S b S \\ +1) S & \rightarrow \varepsilon +\end{align*} + +Расширим вышеупомянутую грамматику, добавив новый стартовый нетерминал S', и далее будем работать с этой расширенной грамматикой: +\begin{align*} +0)& S \rightarrow a S b S \\ +1)& S \rightarrow \varepsilon \\ +2)& S' \rightarrow S \$ +\end{align*} + + +\begin{example} +Пример ядра и замыкания. + +Возьмем правило 2 нашей грамматики, предположим, что мы только начинаем разбирать данное правило. + +Ядром в таком случае является item исходного правила: $S' \rightarrow \cdot S \$$ + +При замыкании добавятся ещё два item'a с правилами по выводу нетерминала `$S$', поэтому получаем три item'a: $S' \rightarrow \cdot S\$$, $S \rightarrow \cdot aSbS$ и $S \rightarrow \cdot \varepsilon$ +\end{example} + +\begin{example} +Пример построения LR(0)-автомата для нашей грамматики с применением замыкания. +\begin{enumerate} +\item Добавляем стартовое состояние: item правила 0 и его замыкание (вместо item'a $S \rightarrow .\varepsilon$ будем писать $S \rightarrow .$). + +\input{figures/GLR/LR0/state0.tex} + +\item По `$S$' добавляем переход из стартового состояния в новое состояние 1. + +\input{figures/GLR/LR0/state1.tex} + +\item По '$\$$' добавляем переход из состояния 1 в новое состояние 2. + +\input{figures/GLR/LR0/state2.tex} + +\item По `$a$' добавляем переход из стартового состояния в новое состояние 3 и делаем его замыкание. Также добавляем переход по `$a$' из этого состояния в себя же. + +\input{figures/GLR/LR0/state3.tex} + +\item По `$S$' добавляем переход из состояния 3 в новое состояние 4. + +\input{figures/GLR/LR0/state4.tex} + +\item По `$b$' добавляем переход из состояния 4 в новое состояние 5 и делаем его замыкание. Также добавляем переход по `$a$' из этого состояния в состояние 3. + +\input{figures/GLR/LR0/state5.tex} + + +\item По `$S$' добавляем переход из состояния 5 в новое состояние 6. Завершаем построение LR-автомата. + +\input{figures/GLR/LR0/complete.tex} + +\end{enumerate} +\end{example} + +Далее будем использовать этот автомат для построения управляющей таблицы. + +\begin{example} +Пример управляющей LR(0) таблицы. + +\begin{tabular}{c||c|c|c||c} + & a & b & \$ & S \\ \hline + \hline 0 & $s_3$, $r_1$ & $r_1$ & $r_1$ & 1 \\ + \hline 1 & & & acc & \\ + \hline 2 & $r_2$ & $r_2$ & $r_2$ & \\ + \hline 3 & $s_3$, $r_1$ & $r_1$ & $r_1$ & 4 \\ + \hline 4 & & $s_5$ & & \\ + \hline 5 & $s_3, r_1$ & $r_1$ & $r_1$ & 6 \\ + \hline 6 & $r_0$ & $r_0$ & $r_0$ & + +\end{tabular} + +Как видим, в данном случае в таблице присутствуют shift-reduce конфликты. В случае, когда не удаётся построить таблицу без конфликтов, говорят, что грамматика не LR(0). + +\qed +\end{example} + + +\begin{example} +Пример управляющей LR(1) таблицы. Автомат тот же, однако команды \textit{reduce} расставляются с использованием FOLLOW. + +$$ +\textit{FOLLOW}_1(S) = \{b, \$\} +$$ + +\begin{tabular}{c||c|c|c||c} + & a & b & \$ & S \\ \hline + \hline 0 & $s_3$ & $r_1$ & $r_1$ & 1 \\ + \hline 1 & & & acc & \\ + \hline 2 & & & & \\ + \hline 3 & $s_3$ & $r_1$ & $r_1$ & 4 \\ + \hline 4 & & $s_5$ & & \\ + \hline 5 & $s_3$ & $r_1$ & $r_1$ & 6 \\ + \hline 6 & & $r_0$ & $r_0$ & \\ [1ex] +\end{tabular} + +В данном случае в таблице отсутствуют shift-reduce конфликты. То есть наша грамматика SLR(1), но не LR(0). + +\qed +\end{example} + +\begin{example} +Пример LR-разбора входного слова abab\$ из языка нашей грамматики с использованием построенных ранее LR-автомата и управляющей таблицы. +\begin{enumerate} +\item Начало разбора. На стеке --- стартовое состояние 0. \\ \\ +Вход: \, +\begin{tabular}[c]{ |c|c|c|c|c| } + \hline \textcolor{red}{a} & b & a & b & \$ \\ \hline +\end{tabular} \\ +Стек: \, +\begin{tabular}[c]{ |c|c } + \hline 0 & \\ \hline +\end{tabular} +\\ +\item Выполняем shift 3: сдвигаем указатель на входе, кладем на стек `$a$', новое состояние 3 и переходим в него. \\ \\ +Вход: \, +\begin{tabular}[c]{ |c|c|c|c|c| } + \hline a & \textcolor{red}{b} & a & b & \$ \\ \hline +\end{tabular} \\ +Стек: \, +\begin{tabular}[c]{ |c|c|c|c } + \hline 0 & a & 3 & \\ \hline +\end{tabular} +\\ +\item Выполняем reduce 1 (кладем на стек `$S$'), кладем новое состояние 4 и переходим в него. \\ \\ +Вход: \, +\begin{tabular}[c]{ |c|c|c|c|c| } + \hline a & \textcolor{red}{b} & a & b & \$ \\ \hline +\end{tabular} \\ +Стек: \, +\begin{tabular}[c]{ |c|c|c|c|c|c } + \hline 0 & a & 3 & S & 4 & \\ \hline +\end{tabular} +\\ +\item Выполняем shift 5: сдвигаем указатель на входе, кладем на стек `$b$', новое состояние 5 и переходим в него. \\ \\ +Вход: \, +\begin{tabular}[c]{ |c|c|c|c|c| } + \hline a & b & \textcolor{red}{a} & b & \$ \\ \hline +\end{tabular}\\ +Стек: \, +\begin{tabular}[c]{ |c|c|c|c|c|c|c|c } + \hline 0 & a & 3 & S & 4 & b & 5 & \\ \hline +\end{tabular} +\\ +\item Выполняем shift 3. \\ \\ +Вход: \, +\begin{tabular}[c]{ |c|c|c|c|c| } + \hline a & b & a & \textcolor{red}{b} & \$ \\ \hline +\end{tabular} \\ +Стек: \, +\begin{tabular}[c]{ |c|c|c|c|c|c|c|c|c|c } + \hline 0 & a & 3 & S & 4 & b & 5 & a & 3 & \\ \hline +\end{tabular} +\\ +\item Выполняем reduce 1, кладем новое состояние 4 и переходим в него. \\ \\ +Вход: \, +\begin{tabular}[c]{ |c|c|c|c|c| } + \hline a & b & a & \textcolor{red}{b} & \$ \\ \hline +\end{tabular}\\ +Стек: \, +\begin{tabular}[c]{ |c|c|c|c|c|c|c|c|c|c|c|c } + \hline 0 & a & 3 & S & 4 & b & 5 & a & 3 & S & 4 & \\ \hline +\end{tabular} +\\ +\item Выполняем shift 5. \\ \\ +Вход: \, +\begin{tabular}[c]{ |c|c|c|c|c| } + \hline a & b & a & b & \textcolor{red}{\$} \\ \hline +\end{tabular} \\ +Стек: \, +\begin{tabular}[c]{ |c|c|c|c|c|c|c|c|c|c|c|c|c|c } + \hline 0 & a & 3 & S & 4 & b & 5 & a & 3 & S & 4 & b & 5 & \\ \hline +\end{tabular} +\\ +\item Выполняем reduce 1, кладем новое состояние 6 и переходим в него. \\ \\ +Вход: \, +\begin{tabular}[c]{ |c|c|c|c|c| } + \hline a & b & a & b & \textcolor{red}{\$} \\ \hline +\end{tabular} \\ +Стек: \, +\begin{tabular}[c]{ |c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c } + \hline 0 & a & 3 & S & 4 & b & 5 & a & 3 & S & 4 & b & 5 & S & 6 & \\ \hline +\end{tabular} +\\ +\item Выполняем reduce 0 (снимаем со стека 8 элементов и кладем `$S$'), оказываемся в состоянии 5 и делаем переход в новое состояние 6 с добавлением его на стек. \\ \\ +Вход: \, +\begin{tabular}[c]{ |c|c|c|c|c| } + \hline a & b & a & b & \textcolor{red}{\$} \\ \hline +\end{tabular}\\ +Стек: \, +\begin{tabular}[c]{ |c|c|c|c|c|c|c|c|c|c } + \hline 0 & a & 3 & S & 4 & b & 5 & S & 6 & \\ \hline +\end{tabular} +\\ +\item Снова выполняем reduce 0, оказываемся в состоянии 0 и делаем переход в новое состояние 1 с добавлением его на стек. Заканчиваем разбор. \\ \\ +Вход: \, +\begin{tabular}[c]{ |c|c|c|c|c| } + \hline a & b & a & b & \textcolor{red}{\$} \\ \hline +\end{tabular} \\ +Стек: \, +\begin{tabular}[c]{ |c|c|c|c } + \hline 0 & S & 1 & \\ \hline +\end{tabular} +\end{enumerate} +\qed +\end{example} + +\begin{example} +Пример CLR автомата. + +\begin{center} + \input{figures/GLR/CLR_example} +\end{center} +\qed +\end{example} + + +Существуют и другие модификации, например LALR(1) + +На практике конфликты стараются решать ещё и на этапе генерации. +Прикладные инструменты могут сгенерировать парсер по неоднозначной грамматике: из переноса или свёртки выбирать перенос, из нескольких свёрток --- первую в каком-то порядке (обычно в порядке появления соответствующих продукций в грамматике). + +\subsection{Сравнение классов LL и LR} + +Иерархию языков, распознаваемых различными классами алгоритмов, можно представить следующим образом. + +\begin{center} + \input{figures/GLR/LL_LR.tex} +\end{center} + +Из диаграммы видно, что класс языков, распознаваемых LL(k) алгоритмом уже, чем класс языков, распознаваемый LR(k) алгоритмом, при любом конечном $k$. Приведём несколько примеров. +\begin{enumerate} +\item $L = \{a^mb^nc \mid m \geq n \geq 0\} $ является LR(0), но для него не существует LL(1) грамматики. +\item $L = \{ a^n b^n + a^n c^n \mid n > 0\}$ является LR, но не LL. +\item Больше примеров можно найти в работе Джона Битти~\cite{BEATTY1980193}. +\end{enumerate} + +\section{GLR и его применение для КС запросов} + +Алгоритм LR довольно эффективен, однако позволяет работать не со всеми КС-грамматиками, а только с их подмножеством LR(k). Если грамматика находится за рамками допускаемого класса, некоторые ячейки управляющей таблицы могут содержать несколько значений. В этом случае грамматика отвергалась анализатором. + +Чтобы допустить множественные значения в ячейках управляющей таблицы, потребуется некоторый вид недетерминизма, который даст возможность анализатору обрабатывать несколько возможных вариантов синтаксического разбора параллельно. Именно это и предлагает анализатор Generalized LR (GLR)~\cite{tomita-1987-efficient}. Далее мы рассмотрим общий принцип работы, проиллюстрируем его с помощью примера, а также рассмотрим модификации GLR. + +\subsection{Классический GLR алгоритм} + +Впервые GLR парсер был представлен Масару Томитой в 1987~\cite{tomita-1987-efficient}. В целом, алгоритм работы идентичен LR той разницей, что управляющая таблица модифицирована таким образом, чтобы допускать множественные значения в ячейках. Интерпретатор автомата изменён соответствующим образом. + +Для того, чтобы избежать дублирования информации при обработке неоднозначностей, стоит использовать более сложную структуру стека: \textit{граф-структурированный стек} или (\textit{GSS}, Graph Structured Stack). Это направленный граф, в котором вершины соответствуют элементам стека, а ребра их соединяют по правилам управляющей таблицы. У каждой вершины может быть несколько входящих и исходящих дуг: таким образом реализуется то объединение одинаковых состяний и ветвление в случае неоднозначности. + +\begin{example} + \label{glr:example} + Рассмотрим пример GLR разбора с использованием GSS. + + Возьмем грамматику $G$ следующего вида: + \begin{align*} + &0.\quad S' \to S\$ \\ + &1.\quad S \to abC \\ + &2.\quad S \to aBC \\ + &3.\quad B \to b \\ + &4.\quad C \to c + \end{align*} + + Входное слово $ w $: + \begin{align*} + w = abc\$ + \end{align*} + + Построим для данной грамматики LR автомат: + +\begin{center} + \input{figures/GLR/GLR_example.tex} +\end{center} + + И управляющую таблицу: + + \begin{tabular}{c||c|c|c|c||c|c|c} + & a & b & c & \$ & B & C & S \\ \hline + \hline 0 & $s_2$ & & & & & 1 & \\ + \hline 1 & & & & acc & & & \\ + \hline 2 & & $s_3$ & & & 4 & & \\ + \hline 3 & & & $s_6$, $r_3$ & & & 5 & \\ + \hline 4 & & & $s_6$ & & & 7 & \\ + \hline 5 & & & & $r_1$ & & & \\ + \hline 6 & & & & $r_4$ & & & \\ + \hline 7 & & & & $r_2$ & & & + \end{tabular} + + Разберем слово $w$ с помощью алгоритма GLR. Использована следующая аннотация: вершины-состояния обозначены кругами, вершины-символы --- прямоугольниками. + \begin{enumerate} + \item Инициализируем GSS стартовым состоянием $v_0$: \\ \\ + Вход: \, + \begin{tabular}[c]{ |c|c|c|c| } + \hline a & b & c & \$ \\ \hline + \end{tabular} + \qquad GSS: \, + \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] + %uncomment if require: \path (0,306); %set diagram left start at 0, and has height of 306 + + + % Text Node + \draw [line width=0.75] (92, 109) circle [x radius= 13.6, y radius= 13.6] ; + \draw (92,109) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; + % Text Node + \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; + + + \end{tikzpicture} + \\ + + \item Видим входной символ '$a$', ищем соответствующую ему операцию в управляющей таблице --- $shift\ 2$, строим новый узел $v_1$: \\ \\ + Вход: \, + \begin{tabular}[c]{ |c|c|c|c| } + \hline \textcolor{red}{a} & b & c & \$ \\ \hline + \end{tabular} + \qquad GSS: \, + \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] + %uncomment if require: \path (0,306); %set diagram left start at 0, and has height of 306 + + + % Text Node + \draw [line width=0.75] (92, 109) circle [x radius= 13.6, y radius= 13.6] ; + \draw (92,109) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; + % Text Node + \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; + \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; + % Text Node + \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; + % Text Node + \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; + % Text Node + \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; + % Connection + \draw (138,109.84) -- (107.6,109.28) ; + \draw [shift={(105.6,109.25)}, rotate = 361.03999999999996] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (189.4,110) -- (158,110) ; + \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + + \end{tikzpicture} + \\ + + \item Повторяем для символа '$b$', операции $shift\ 3$ и узла $v_2$: \\ \\ + Вход: \, + \begin{tabular}[c]{ |c|c|c|c| } + \hline a & \textcolor{red}{b} & c & \$ \\ \hline + \end{tabular} + \qquad GSS: \, + \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] + %uncomment if require: \path (0,306); %set diagram left start at 0, and has height of 306 + + + % Text Node + \draw [line width=0.75] (92, 109) circle [x radius= 13.6, y radius= 13.6] ; + \draw (92,109) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; + % Text Node + \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; + \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {a}; + % Text Node + \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; + % Text Node + \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; + % Text Node + \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; + % Text Node + \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; + \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; + % Text Node + \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; + % Text Node + \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; + % Connection + \draw (138,109.84) -- (107.6,109.28) ; + \draw [shift={(105.6,109.25)}, rotate = 361.03999999999996] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (189.4,110) -- (158,110) ; + \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (309.4,110) -- (278,110) ; + \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (258,110) -- (218.6,110) ; + \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + + \end{tikzpicture} + \\ + + \item При обработке узла $v_3$ у нас возникает конфликт shift-reduce: $s_6,\ r_3$. Мы смотрим на вершины, смежные $v_2$, на управляющую таблицу и на правило вывода под номером 3 для поиска альтернативного построения стека. Находим $goto\ 4$ и строим вершину $v_3$ с соответствующим переходом по нетерминалу $B$ из $v_1$ (т.к. количество символов в правой части правила вывода 3 равняется 1, значит мы в дереве опустимся на глубину 1 по вершинам-состояниям):\\ \\ + Вход: \, + \begin{tabular}[c]{ |c|c|c|c| } + \hline a & b & c & \$ \\ \hline + \end{tabular} + \qquad GSS: \, + \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] + %uncomment if require: \path (0,422); %set diagram left start at 0, and has height of 422 + + + % Text Node + \draw [line width=0.75] (92, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (92,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; + % Text Node + \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; + \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; + % Text Node + \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; + % Text Node + \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; + % Text Node + \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; + % Text Node + \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; + \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; + % Text Node + \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; + % Text Node + \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; + % Text Node + \draw [line width=0.75] (258,158) -- (276,158) -- (276,182) -- (258,182) -- cycle ; + \draw (267,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {B}; + % Text Node + \draw [line width=0.75] (323, 170) circle [x radius= 13.6, y radius= 13.6] ; + \draw (323,170) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$4$}; + % Text Node + \draw (340,149) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{3}$}; + % Connection + \draw (138,110) -- (107.6,110) ; + \draw [shift={(105.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (189.4,110) -- (158,110) ; + \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (309.4,110) -- (278,110) ; + \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (258,110) -- (218.6,110) ; + \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (309.4,170) -- (278,170) ; + \draw [shift={(276,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (258,168.07) .. controls (230.15,163.58) and (213.3,149.18) .. (207.42,124.89) ; + \draw [shift={(206.99,123.01)}, rotate = 437.91] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + + \end{tikzpicture} + \\ + + \item Читаем символ '$c$' и ищем в управляющей таблице переходы из состояний 3 и 4 (так как узлы $v_2$ и $v_3$ находятся на одном уровне, то есть были построены после чтения одного символа из входного слова). Таким переходом оказывается $s_6$ в обоих случаях, поэтому соединяем узел $v_4$ с обоими рассмотренными узлами:\\ \\ + Вход: \, + \begin{tabular}[c]{ |c|c|c|c| } + \hline a & b & \textcolor{red}{c} & \$ \\ \hline + \end{tabular} + \qquad GSS: \, + \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] + %uncomment if require: \path (0,422); %set diagram left start at 0, and has height of 422 + + + % Text Node + \draw [line width=0.75] (92, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (92,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; + % Text Node + \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; + \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; + % Text Node + \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; + % Text Node + \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; + % Text Node + \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; + % Text Node + \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; + \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; + % Text Node + \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; + % Text Node + \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; + % Text Node + \draw [line width=0.75] (258,158) -- (276,158) -- (276,182) -- (258,182) -- cycle ; + \draw (267,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {B}; + % Text Node + \draw [line width=0.75] (323, 170) circle [x radius= 13.6, y radius= 13.6] ; + \draw (323,170) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$4$}; + % Text Node + \draw (340,149) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{3}$}; + % Text Node + \draw [line width=0.75] (374,98) -- (392,98) -- (392,122) -- (374,122) -- cycle ; + \draw (383,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; + % Text Node + \draw [line width=0.75] (374,158) -- (392,158) -- (392,182) -- (374,182) -- cycle ; + \draw (383,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; + % Text Node + \draw [line width=0.75] (437, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$6$}; + % Text Node + \draw (450,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{4}$}; + % Connection + \draw (138,110) -- (107.6,110) ; + \draw [shift={(105.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (189.4,110) -- (158,110) ; + \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (309.4,110) -- (278,110) ; + \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (258,110) -- (218.6,110) ; + \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (309.4,170) -- (278,170) ; + \draw [shift={(276,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (258,168.07) .. controls (230.15,163.58) and (213.3,149.18) .. (207.42,124.89) ; + \draw [shift={(206.99,123.01)}, rotate = 437.91] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (374,110) -- (338.6,110) ; + \draw [shift={(336.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,110) -- (394,110) ; + \draw [shift={(392,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (435.82,123.55) .. controls (435.9,150.31) and (416.89,165.24) .. (393.78,168.34) ; + \draw [shift={(392,168.55)}, rotate = 353.9] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (374,170) -- (338.6,170) ; + \draw [shift={(336.6,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + + \end{tikzpicture} + \\ + + \item При обработке узла $v_4$ находим соответствующею 6-ому состоянию редукцию по правилу 4. Его правая часть содержит один символ '$c$', 2 вершины-символа с которым достижимы из $v_4$. Находим вершины-состояния, которые смежны с этими вершинами-символами и обрабатываем переходы по левой части правила 4. Такими переходами по нетерминалу $C$ оказываются $5$ и $7$. Строим соответствующие им вершины $v_5$ и $v_6$:\\ \\ + Вход: \, + \begin{tabular}[c]{ |c|c|c|c| } + \hline a & b & c & \$ \\ \hline + \end{tabular} + \qquad GSS: \, + \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] + %uncomment if require: \path (0,422); %set diagram left start at 0, and has height of 422 + + + % Text Node + \draw [line width=0.75] (92, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (92,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; + % Text Node + \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; + \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; + % Text Node + \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; + % Text Node + \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; + % Text Node + \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; + % Text Node + \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; + \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; + % Text Node + \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; + % Text Node + \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; + % Text Node + \draw [line width=0.75] (258,158) -- (276,158) -- (276,182) -- (258,182) -- cycle ; + \draw (267,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {B}; + % Text Node + \draw [line width=0.75] (323, 170) circle [x radius= 13.6, y radius= 13.6] ; + \draw (323,170) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$4$}; + % Text Node + \draw (340,149) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{3}$}; + % Text Node + \draw [line width=0.75] (374,98) -- (392,98) -- (392,122) -- (374,122) -- cycle ; + \draw (383,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; + % Text Node + \draw [line width=0.75] (374,158) -- (392,158) -- (392,182) -- (374,182) -- cycle ; + \draw (383,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; + % Text Node + \draw [line width=0.75] (437, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$6$}; + % Text Node + \draw (450,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{4}$}; + % Text Node + \draw [line width=0.75] (372,38) -- (392,38) -- (392,62) -- (372,62) -- cycle ; + \draw (382,50) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; + % Text Node + \draw [line width=0.75] (372,218) -- (392,218) -- (392,242) -- (372,242) -- cycle ; + \draw (382,230) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; + % Text Node + \draw [line width=0.75] (437, 50) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,50) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$5$}; + % Text Node + \draw [line width=0.75] (437, 231) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,231) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$7$}; + % Text Node + \draw (452,28) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{5}$}; + % Text Node + \draw (452,208) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{6}$}; + % Connection + \draw (138,110) -- (107.6,110) ; + \draw [shift={(105.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (189.4,110) -- (158,110) ; + \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (309.4,110) -- (278,110) ; + \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (258,110) -- (218.6,110) ; + \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (309.4,170) -- (278,170) ; + \draw [shift={(276,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (258,168.07) .. controls (230.15,163.58) and (213.3,149.18) .. (207.42,124.89) ; + \draw [shift={(206.99,123.01)}, rotate = 437.91] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (374,110) -- (338.6,110) ; + \draw [shift={(336.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,110) -- (394,110) ; + \draw [shift={(392,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (435.82,123.55) .. controls (435.9,150.31) and (416.89,165.24) .. (393.78,168.34) ; + \draw [shift={(392,168.55)}, rotate = 353.9] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (374,170) -- (338.6,170) ; + \draw [shift={(336.6,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (372,50.52) .. controls (341.88,50.18) and (326.06,64.88) .. (324.53,94.64) ; + \draw [shift={(324.46,96.48)}, rotate = 271.78] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (372,229.65) .. controls (341.88,230.53) and (326.05,215.79) .. (324.5,185.41) ; + \draw [shift={(324.42,183.53)}, rotate = 448.21] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,50) -- (394,50) ; + \draw [shift={(392,50)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,230.75) -- (394,230.22) ; + \draw [shift={(392,230.18)}, rotate = 361.03999999999996] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + + \end{tikzpicture} + \\ + + \item При обработке узлов $v_5$ и $v_6$ находим редукции с символом '$S$' в левой части и тремя символами в правой. Возвращаемся на 3 вершины-состояния назад и строим вершину $v_7$ с переходом по $S$: \\ \\ + Вход: \, + \begin{tabular}[c]{ |c|c|c|c| } + \hline a & b & c & \$ \\ \hline + \end{tabular} + \qquad GSS: \, + \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] + %uncomment if require: \path (0,422); %set diagram left start at 0, and has height of 422 + + + % Text Node + \draw [line width=0.75] (92, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (92,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; + % Text Node + \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; + \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; + % Text Node + \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; + % Text Node + \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; + % Text Node + \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; + % Text Node + \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; + \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; + % Text Node + \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; + % Text Node + \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; + % Text Node + \draw [line width=0.75] (258,158) -- (276,158) -- (276,182) -- (258,182) -- cycle ; + \draw (267,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {B}; + % Text Node + \draw [line width=0.75] (323, 170) circle [x radius= 13.6, y radius= 13.6] ; + \draw (323,170) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$4$}; + % Text Node + \draw (340,149) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{3}$}; + % Text Node + \draw [line width=0.75] (374,98) -- (392,98) -- (392,122) -- (374,122) -- cycle ; + \draw (383,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; + % Text Node + \draw [line width=0.75] (374,158) -- (392,158) -- (392,182) -- (374,182) -- cycle ; + \draw (383,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; + % Text Node + \draw [line width=0.75] (437, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$6$}; + % Text Node + \draw (450,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{4}$}; + % Text Node + \draw [line width=0.75] (372,38) -- (392,38) -- (392,62) -- (372,62) -- cycle ; + \draw (382,50) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; + % Text Node + \draw [line width=0.75] (372,218) -- (392,218) -- (392,242) -- (372,242) -- cycle ; + \draw (382,230) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; + % Text Node + \draw [line width=0.75] (437, 50) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,50) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$5$}; + % Text Node + \draw [line width=0.75] (437, 231) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,231) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$7$}; + % Text Node + \draw (452,28) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{5}$}; + % Text Node + \draw (452,208) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{6}$}; + % Text Node + \draw [line width=0.75] (373,278) -- (391,278) -- (391,302) -- (373,302) -- cycle ; + \draw (382,290) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {S}; + % Text Node + \draw [line width=0.75] (437, 290) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,290) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$1$}; + % Text Node + \draw (452,268) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{7}$}; + % Connection + \draw (138,110) -- (107.6,110) ; + \draw [shift={(105.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (189.4,110) -- (158,110) ; + \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (309.4,110) -- (278,110) ; + \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (258,110) -- (218.6,110) ; + \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (309.4,170) -- (278,170) ; + \draw [shift={(276,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (258,168.07) .. controls (230.15,163.58) and (213.3,149.18) .. (207.42,124.89) ; + \draw [shift={(206.99,123.01)}, rotate = 437.91] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (374,110) -- (338.6,110) ; + \draw [shift={(336.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,110) -- (394,110) ; + \draw [shift={(392,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (435.82,123.55) .. controls (435.9,150.31) and (416.89,165.24) .. (393.78,168.34) ; + \draw [shift={(392,168.55)}, rotate = 353.9] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (374,170) -- (338.6,170) ; + \draw [shift={(336.6,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (372,50.52) .. controls (341.88,50.18) and (326.06,64.88) .. (324.53,94.64) ; + \draw [shift={(324.46,96.48)}, rotate = 271.78] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (372,229.65) .. controls (341.88,230.53) and (326.05,215.79) .. (324.5,185.41) ; + \draw [shift={(324.42,183.53)}, rotate = 448.21] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,50) -- (394,50) ; + \draw [shift={(392,50)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,230.75) -- (394,230.22) ; + \draw [shift={(392,230.18)}, rotate = 361.03999999999996] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,290) -- (393,290) ; + \draw [shift={(391,290)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (373,289.72) .. controls (234.96,286.59) and (143.34,231.38) .. (98.15,124.08) ; + \draw [shift={(97.47,122.46)}, rotate = 427.47] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + + \end{tikzpicture} + \\ + \item Наконец, обрабатывая вершину $v_7$, читаем символ '$\$$' и строим узел $v_8$, который соответствует допускающим состоянием: \\ \\ + Вход: \, + \begin{tabular}[c]{ |c|c|c|c| } + \hline a & b & c & \textcolor{red}{\$} \\ \hline + \end{tabular} + \qquad GSS: \, + \begin{tikzpicture}[x=0.5pt,y=0.5pt,yscale=-1,xscale=1] + %uncomment if require: \path (0,422); %set diagram left start at 0, and has height of 422 + + + % Text Node + \draw [line width=0.75] (92, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (92,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$0$}; + % Text Node + \draw [line width=0.75] (138,98) -- (156,98) -- (156,122) -- (138,122) -- cycle ; + \draw (147,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {а}; + % Text Node + \draw [line width=0.75] (203, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (203,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$2$}; + % Text Node + \draw (110,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{0}$}; + % Text Node + \draw (220,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{1}$}; + % Text Node + \draw [line width=0.75] (258,98) -- (276,98) -- (276,122) -- (258,122) -- cycle ; + \draw (267,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {b}; + % Text Node + \draw [line width=0.75] (323, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (323,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$3$}; + % Text Node + \draw (340,90) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{2}$}; + % Text Node + \draw [line width=0.75] (258,158) -- (276,158) -- (276,182) -- (258,182) -- cycle ; + \draw (267,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {B}; + % Text Node + \draw [line width=0.75] (323, 170) circle [x radius= 13.6, y radius= 13.6] ; + \draw (323,170) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$4$}; + % Text Node + \draw (340,149) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{3}$}; + % Text Node + \draw [line width=0.75] (374,98) -- (392,98) -- (392,122) -- (374,122) -- cycle ; + \draw (383,110) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; + % Text Node + \draw [line width=0.75] (374,158) -- (392,158) -- (392,182) -- (374,182) -- cycle ; + \draw (383,170) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {c}; + % Text Node + \draw [line width=0.75] (437, 110) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,110) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$6$}; + % Text Node + \draw (450,89) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{4}$}; + % Text Node + \draw [line width=0.75] (372,38) -- (392,38) -- (392,62) -- (372,62) -- cycle ; + \draw (382,50) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; + % Text Node + \draw [line width=0.75] (372,218) -- (392,218) -- (392,242) -- (372,242) -- cycle ; + \draw (382,230) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {C}; + % Text Node + \draw [line width=0.75] (437, 50) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,50) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$5$}; + % Text Node + \draw [line width=0.75] (437, 231) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,231) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$7$}; + % Text Node + \draw (452,28) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{5}$}; + % Text Node + \draw (452,208) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{6}$}; + % Text Node + \draw [line width=0.75] (373,278) -- (391,278) -- (391,302) -- (373,302) -- cycle ; + \draw (382,290) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {S}; + % Text Node + \draw [line width=0.75] (437, 290) circle [x radius= 13.6, y radius= 13.6] ; + \draw (437,290) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$1$}; + % Text Node + \draw (452,268) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{7}$}; + % Text Node + \draw [line width=0.75] (488,278) -- (506,278) -- (506,302) -- (488,302) -- cycle ; + \draw (497,290) node [scale=1,color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {\$}; + % Text Node + \draw [line width=0.75] (557, 290) circle [x radius= 17.8, y radius= 17.8] ; + \draw (557,290) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {acc}; + % Text Node + \draw (575,262) node [color={rgb, 255:red, 62; green, 45; blue, 45 } ,opacity=1 ] {$v_{8}$}; + % Connection + \draw (138,110) -- (107.6,110) ; + \draw [shift={(105.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (189.4,110) -- (158,110) ; + \draw [shift={(156,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (309.4,110) -- (278,110) ; + \draw [shift={(276,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (258,110) -- (218.6,110) ; + \draw [shift={(216.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (309.4,170) -- (278,170) ; + \draw [shift={(276,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (258,168.07) .. controls (230.15,163.58) and (213.3,149.18) .. (207.42,124.89) ; + \draw [shift={(206.99,123.01)}, rotate = 437.91] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (374,110) -- (338.6,110) ; + \draw [shift={(336.6,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,110) -- (394,110) ; + \draw [shift={(392,110)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (435.82,123.55) .. controls (435.9,150.31) and (416.89,165.24) .. (393.78,168.34) ; + \draw [shift={(392,168.55)}, rotate = 353.9] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (374,170) -- (338.6,170) ; + \draw [shift={(336.6,170)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (372,50.52) .. controls (341.88,50.18) and (326.06,64.88) .. (324.53,94.64) ; + \draw [shift={(324.46,96.48)}, rotate = 271.78] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (372,229.65) .. controls (341.88,230.53) and (326.05,215.79) .. (324.5,185.41) ; + \draw [shift={(324.42,183.53)}, rotate = 448.21] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,50) -- (394,50) ; + \draw [shift={(392,50)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,230.75) -- (394,230.22) ; + \draw [shift={(392,230.18)}, rotate = 361.03999999999996] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (423.4,290) -- (393,290) ; + \draw [shift={(391,290)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (373,289.72) .. controls (234.96,286.59) and (143.34,231.38) .. (98.15,124.08) ; + \draw [shift={(97.47,122.46)}, rotate = 427.47] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (488,290) -- (452.6,290) ; + \draw [shift={(450.6,290)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + % Connection + \draw (539.2,290) -- (508,290) ; + \draw [shift={(506,290)}, rotate = 360] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ; + + + \end{tikzpicture} + \\ + \end{enumerate} + + + +\end{example} + +\subsection{Модификации GLR} +Алгоритм, представленный Томитой имел большой недостаток: он корректно работал не со всеми КС грамматиками, хоть и расширял класс допустимых LR анализаторами. Объем потребляемой памяти классическим GLR можно оценить как $ O(n^3)$ с учетом оптимизаций, о которых говорилось ранее. + +Спустя некоторое время после публикации Томита-парсера, Элизабет Скотт и Эндриан Джонстоун представили $RNGLR$ (Right Nulled GLR)~\cite{Scott:2006:RNG:1146809.1146810} --- модифицированная версия GLR, которая решала проблему скрытых рекурсий. Это позволило расширить класс допускаемых грамматик до КС. Однако объем потребляемой памяти можно оценить сверху уже полиномом $O(n^{k+1})$, где k --- длина самого длинного правила грамматики, что несколько ухудшило оценку классического GLR. + +С этой проблемой справился BRNGLR (Binary RNGLR)~\cite{Scott:2007:BCT:1289813.1289815}. За счет бинаризации удалось получить кубическую оценку сложности и при этом также, как и RNGLR, допускать все КС грамматики. + +Подробное описание разных вариаций и история: PhD~\cite{Economopoulos2006GeneralisedLP} + +Кроме того, GLR довольно естесственно обобщается до решения задачи поиска путей с КС ограничениями. Это происходит следующим образом: элементами во входной структуре теперь будем считать не позиции символа в слове, а вершины графа (то есть ``позици'' и множество смежных вершин). Это приводит к тому, что при применении операции shift, следующих символов может быть несколько и каждый из них должен быть рассмотрен отдельно, сдвигаясь по соответствующему ребру и проходя входной граф в ширину. Подробное описание алгоритма и псевдокод представлены в работе~\cite{10.1007/978-3-319-41579-6_22}. + +%\section{Вопросы и задачи} +%\begin{enumerate} +% \item Постройте LR автомат и управляющую таблицу для грамматики $G_1$: $S \to a S b$; $S \to \epsilon$. +% \item Постройте LR автомат и управляющую таблицу для грамматики $G_2$: $S \to S S S$; $S \to S S$; $S \to a$. +% \item Проведите GLR разбор для грамматики $G_2$ и входного слова $w = aaa\$$. +% \item Реализуйте LR анализатор на любом языке программирования. Программа должна принимать на вход файл с однозначной грамматикой и входное слово, строить LR автомат и управляющую таблицу (во внутреннем представлении), и сообщать, выводимо ли входное слово в данной грамматике. +% \item[6*.] Реализуйте GLR анализатор на любом языке программирования. Программа должна принимать на вход файл с однозначной грамматикой и входное слово, работать согласно алгоритму GLR и сохранять GSS, а также сообщать, выводимо ли входное слово в данной грамматике. +%\end{enumerate} diff --git a/tex/Matrix-based_CFPQ.tex b/tex/Matrix-based_CFPQ.tex new file mode 100644 index 0000000..6cab06b --- /dev/null +++ b/tex/Matrix-based_CFPQ.tex @@ -0,0 +1,367 @@ +\chapter[Контекстно-свободная достижимость через произведение матриц]{Контекстно-свободная достижимость через произведение матриц}\label{chpt:MatrixBasedAlgos} +\chaptermark{КС достижимость через произведение матриц} + +В данном разделе мы рассмотрим алгоритм решения задачи контекстно-свободной достижимости, основанный на произведении матриц. +Будет показано, что при использовании конъюнктивных грамматик, представленный алгоритм находит переапроксимацию истинного решения задачи. + +\section[Алгоритм контекстно-свободной достижимости через произведение матриц]{Алгоритм контекстно-свободной достижимости через произведение матриц\sectionmark{Алгоритм КС достижимости через произведение матриц}} +\sectionmark{Алгоритм КС достижимости через произведение матриц} +\label{Matrix-CFPQ} + +В главе~\ref{graph:CYK}~был изложен алгоритм для решения задачи КС достижимости на основе CYK. +Заметим, что обход матрицы напоминает умножение матриц в ячейках которых множества нетерминалов: +\begin{align*} +M_3 = &M_1 \times M_2 \\ +M_3[i,j] = &\sum_{k=1}^{n} M[i,k] * M[k,j] +\end{align*} +, где сумма --- это объединение множеств: +\[ +\sum_{k=1}^{n} = \bigcup_{k=1}^{n} +\] +, а поэлементное умножение определено следующим образом: +\[ +S_1 * S_2 = \{N_1^0 ... N_1^m\} * \{N_2^0 ... N_2^l\} = \{N_3 \mid (N_3 \rightarrow N_1^i N_2^j) \in P\}. +\] +Таким образом, алгоритм решения задачи КС достижимости может быть выражена в терминах перемножения матриц над полукольцом с соответствующими операциями. + +Для частного случая этой задачи, синтаксического анализа линейного входа, существует алгоритм Валианта~\cite{Valiant:1975:GCR:1739932.1740048}, использующий эту идею. +Однако он не обобщается на графы из-за того, что существенно использует возможность упорядочить обход матрицы (см. разницу в CYK для линейного случая и для графа). +Поэтому, хотя для линейного случая алгоритм Валианта является алгоритмом синтаксического анализа для произвольных КС грамматик за субкубическое время, его обобщение до задачи КС достижимости в произвольных графах с сохранением асимптотики является нетривиальной задачей~\cite{Yannakakis}. +В настоящее время алгоритм с субкубической сложностью получен только для частного случая --- языка Дика с одним типом скобок --- Филипом Брэдфорlом~\cite{8249039}. + +В случае с линейным входом, отдельного внимания заслуживает работа Лиллиан Ли (Lillian Lee)~\cite{Lee:2002:FCG:505241.505242}, где она показывает, что задача перемножения матриц сводима к синтаксическому анализу линейного входа. Аналогичных результатов для графов на текущий момент не известно. + +Поэтому рассмотрим более простую идею, изложенную в статье Рустама Азимова~\cite{Azimov:2018:CPQ:3210259.3210264}: будем строить транзитивное замыкание графа через наивное (не через возведение в квадрат) умножение матриц. + +Пусть $\mathcal{G} = (V, E)$ --- входной граф и $G = (N,\Sigma,P)$ --- входная грамматика. Тогда алгоритм может быть сформулирован, как представлено в листинге~\ref{alg:graphParse}. + +\begin{algorithm}[H] +\begin{algorithmic}[1] +\caption{Context-free recognizer for graphs} +\label{alg:graphParse} +\Function{contextFreePathQuerying}{$\mathcal{G}$, G} + + \State{$n \gets$ количество узлов в $\mathcal{G}$} + \State{$E \gets$ направленные ребра в $\mathcal{G}$} + \State{$P \gets$ набор продукций из $G$} + \State{$T \gets$ матрица $n \times n$, в которой каждый элемент $\varnothing$} + \ForAll{$(i,x,j) \in E$} + \Comment{Инициализация матрицы} + \State{$T_{i,j} \gets T_{i,j} \cup \{A~|~(A \rightarrow x) \in P \}$} + \EndFor + \ForAll{$i \in 0\ldots n-1$} + \Comment{Добавление петель для нетерминалов, порождающих пустую строку} + \State{$T_{i,i} \gets T_{i,i} \cup \{ A \in N \mid A \to \varepsilon \}$} + \EndFor + \While{матрица $T$ меняется} + + \State{$T \gets T \cup (T \times T)$} + \Comment{Вычисление транзитивного замыкания} + \EndWhile +\State \Return $T$ +\EndFunction +\end{algorithmic} +\end{algorithm} + + +\begin{example}[Пример работы] + +Пусть есть граф $\mathcal{G}$: +\begin{center} + \input{figures/graph/graph0.tex} +\end{center} + +и грамматика $G$: +\begin{align*} +S &\to A B &A \to a \\ +S &\to A S_1 &B \to b\\ +S_1 &\to S B +\end{align*} + + +Пусть $T_i$ --- матрица, полученная из $T$ после применения цикла, описанного в строках \textbf{8-9} алгоритма~\ref{alg:graphParse}, $i$ раз. +Тогда $T_0$, полученная напрямую из графа, выглядит следующим образом: + +\[ +T_0 = \begin{pmatrix} + \varnothing & \{A\} & \varnothing & \{B\} \\ + \varnothing & \varnothing & \{A\} & \varnothing \\ + \{A\} & \varnothing & \varnothing & \varnothing \\ + \{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} +\] + +Далее показано получение матрицы $T_1$. + +\[ +T_0 \times T_0 = \begin{pmatrix} + \varnothing & \varnothing & \varnothing & \varnothing \\ + \varnothing & \varnothing & \varnothing & \varnothing \\ + \varnothing & \varnothing & \varnothing & \{S\} \\ + \varnothing & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} +\] + +\[ +T_1 = T_0 \cup (T_0 \times T_0) = \begin{pmatrix} + \varnothing & \{A\} & \varnothing & \{B\} \\ + \varnothing & \varnothing & \{A\} & \varnothing \\ + \{A\} & \varnothing & \varnothing & \cellcolor{lightgray} \{\pmb{S}\} \\ + \{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} +\] + +После первой итерации цикла нетерминал в ячейку $T[2,3]$ добавился нетерминал $S$. +Это означает, что существует такой путь $\pi$ из вершины 2 в вершину 3 в графе $\mathcal{G}$, что $S \xrightarrow{*} \omega(\pi)$. В данном примере путь состоит из двух ребер $2 \xrightarrow{a} 0$ и $ 0 \xrightarrow{b} 3$, так что $S \xrightarrow{*} ab$. + +Вычисление транзитивного замыкания заканчивается через $k$ итераций, когда достигается неподвижная точка процесса: $T_{k-1} = T_k$. Для данного примера $k = 13$, так как $T_{13} = T_{12}$. Весь процесс работы алгоритма (все матрицы $T_i$) показан ниже (на каждой итерации новые элементы выделены жирным). + +{\footnotesize +\begin{alignat*}{7} +& &&T_2 &&= \begin{pmatrix} +\varnothing & \{A\} & \varnothing & \{B\} \\ +\varnothing & \varnothing & \{A\} & \varnothing \\ +\cellcolor{lightgray} \{A, \pmb{S_1}\} & \varnothing & \varnothing & \{S\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} \ \ \ \ &&T_3 &&= \begin{pmatrix} +\varnothing & \{A\} & \varnothing & \{B\} \\ +\cellcolor{lightgray} \{\pmb{S}\} & \varnothing & \{A\} & \varnothing \\ +\{A, S_1\} & \varnothing & \varnothing & \{S\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} \\ & &&T_4 &&= \begin{pmatrix} +\varnothing & \{A\} & \varnothing & \{B\} \\ +\{S\} & \varnothing & \{A\} & \cellcolor{lightgray} \{\pmb{S_1}\} \\ +\{A, S_1\} & \varnothing & \varnothing & \{S\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} \ \ \ \ &&T_5 &&= \begin{pmatrix} +\varnothing & \{A\} & \varnothing & \cellcolor{lightgray} \{B, \pmb{S}\} \\ +\{S\} & \varnothing & \{A\} & \{S_1\} \\ +\{A, S_1\} & \varnothing & \varnothing & \{S\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} \\ & &&T_6 &&= \begin{pmatrix} +\cellcolor{lightgray} \{\pmb{S_1}\} & \{A\} & \varnothing & \{B, S\} \\ +\{S\} & \varnothing & \{A\} & \{S_1\} \\ +\{A, S_1\} & \varnothing & \varnothing & \{S\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} \ \ \ \ &&T_7 &&= \begin{pmatrix} +\{S_1\} & \{A\} & \varnothing & \{B, S\} \\ +\{S\} & \varnothing & \{A\} & \{S_1\} \\ +\cellcolor{lightgray} \{A, S_1, \pmb{S}\} & \varnothing & \varnothing & \{S\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} \\ +& &&T_8 &&= \begin{pmatrix} +\{S_1\} & \{A\} & \varnothing & \{B, S\} \\ +\{S\} & \varnothing & \{A\} & \{S_1\} \\ +\{A, S_1, S\} & \varnothing & \varnothing & \cellcolor{lightgray} \{S, \pmb{S_1}\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} \ \ \ \ &&T_9 &&= \begin{pmatrix} +\{S_1\} & \{A\} & \varnothing & \{B, S\} \\ +\{S\} & \varnothing & \{A\} & \cellcolor{lightgray} \{S_1, \pmb{S}\} \\ +\{A, S_1, S\} & \varnothing & \varnothing & \{S, S_1\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} \\ & &&T_{10} &&= \begin{pmatrix} +\{S_1\} & \{A\} & \varnothing & \{B, S\} \\ +\cellcolor{lightgray} \{S, \pmb{S_1}\} & \varnothing & \{A\} & \{S_1, S\} \\ +\{A, S_1, S\} & \varnothing & \varnothing & \{S, S_1\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} \ \ \ \ &&T_{11} &&= \begin{pmatrix} +\cellcolor{lightgray} \{S_1, \pmb{S}\} & \{A\} & \varnothing & \{B, S\} \\ +\{S, S_1\} & \varnothing & \{A\} & \{S_1, S\} \\ +\{A, S_1, S\} & \varnothing & \varnothing & \{S, S_1\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} \\ & &&T_{12} &&= \begin{pmatrix} +\{S_1, S\} & \{A\} & \varnothing & \cellcolor{lightgray} \{B, S, \pmb{S_1}\} \\ +\{S, S_1\} & \varnothing & \{A\} & \{S_1, S\} \\ +\{A, S_1, S\} & \varnothing & \varnothing & \{S, S_1\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} \ \ \ \ &&T_{13} &&= \begin{pmatrix} +\{S_1, S\} & \{A\} & \varnothing & \{B, S, S_1\} \\ +\{S, S_1\} & \varnothing & \{A\} & \{S_1, S\} \\ +\{A, S_1, S\} & \varnothing & \varnothing & \{S, S_1\} \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} +\end{alignat*} +} + +Таким образом, результат алгоритма~\ref{alg:graphParse} для нашего примера --- это матрица $T_{13} = T_{12}$. Заметим, что для данного алгоритма приведённый пример также является худшим случаем: на каждой итерации в матрицу добавляется ровно один нетерминал, при том, что необходимо заполнить порядка $O(n^2)$ ячеек. + +\end{example} + + +\subsection{Расширение алгоритма для конъюнктивных грамматик} + +Матричный алгоритм для конъюнктивных грамматик отличается от алгоритма~\ref{alg:graphParse} для контекстно-свободных грамматик только операцией умножения матриц, в остальном алгоритм остается без изменений. Определим операцию умножения матриц. +\begin{definition} + Пусть $M_1$ и $M_2$ матрицы размера $n$. Определим операцию $\circ$ следующим образом: + \[M_1 \circ M_2 = M_3,\] + \[M_3 [i,j] = \{A \mid \exists (A \rightarrow B_1 C_1 \& \ldots \& B_m C_m) \in P, (B_k , C_k) \in d[i,j] \forall k = 1,\ldots,m\}\], + где \[d[i,j] = \bigcup_{k = 1}^{n} M_1 [i,k] \times M_2 [k,j].\] +\end{definition} + +Важно заметить, что алгоритм для конъюнктивных грамматик, в отличие от алгоритма для контекстно-свободных грамматик, дает лишь верхнюю оценку ответа. То есть все нетерминалы, которые должны быть в ячейках матрицы результата, содержатся там, но вместе с ними содержатся и лишние нетерминалы. Рассмотрим пример, иллюстрирующий появление лишних нетерминалов. + +\begin{example} + Грамматика $G$: + \begin{align*} + S &\to AB \& DC & C &\to c \\ + A &\to a & D &\to DC \mid b\\ + B &\to BC \mid b + \end{align*} + Очевидно, что грамматика $G$ задает язык из одного слова $L(G) = \{abc\} = \{abc^*\} \cap \{a^* bc\}$. + + Пусть есть граф $\mathcal{G}$: + \begin{center} + \input{figures/multi/graph0.tex} + \end{center} + Применяя алгоритм, получим, что существует путь из вершины 0 в вершину 4, выводимый из нетерминала $S$. Однако очевидно, что в графе такого пути нет. + Такое поведение алгоритма наблюдается из-за того, что существует путь ``abcc'', соответствующий $L(AB) = \{abc^*\}$ и путь ``aabc'', соответствующий $L(DC) = \{a^{*}bc\}$, но они различны. Однако алгоритм не может это проверить, так как оперирует понятием достижимости между вершинами, а не наличием различных путей. Более того, в общем случае для конъюнктивных грамматик такую проверку реалиховать нельзя. Поэтому для классической семантики достидимости с ограничениями в терминах конъюнктивных грамматик результат работы алгоритма является оценкой сверху. + + Существует альтернативная семантика, когда мы трактуем конъюнкцию в правой части правил как конъюнкцию в Datalog (подробнее о Datalog в параграфе~\ref{Subsection Datalog}). Т.е если есть правило $S \to AB \& DC$, то должен быть путь принадлежащий языку $L(AB)$ и путь принадлежащий языку $L(DC)$. В такой семантике алгоритм дает точный ответ. +\end{example} + +Подробнее алгоритм описан в статье Рустама Азимова и Семёна Григорьева~\cite{565CECD7E8F5C6063935B41DB41797AA37D53B04}. Стоит также отметить, что обобщения данного алгоритма для булевых грамматик не существует, хотя и существует частное решение для случая, когда граф не содержит циклов (является DAG-ом), предложенное Екатериной Шеметовой~\cite{Shemetova2019}. + +\section{Особенности реализации} + +Алгоритмы, описанные выше, удобны с точки зрения реализации тем, что могут быть эффективно реализованы с использованием высокопроизводительных библиотек линейной алгебры, которые эксплуатируют возможности параллельных вычислений на современных CPU и GPGPU~\cite{Mishin:2019:ECP:3327964.3328503}. +Это позволяет с минимальными затратами получить эффективную параллельную реализацию алгоритма для решения задачи КС достижимости в графах. +Благодаря этому, хотя асимптотически приведенные алгоритмы имеют большую сложность чем, скажем, алгоритм Хеллингса, в результате эффективного распараллеливания на практике они работают быстрее однопоточных алгоритмов с лучшей сложностью. + +Далее рассмотрим некоторые детали, упрощающие реализацию с использованием современных библиотек и аппаратного обеспечения. + +Так как множество нетерминалов и правил конечно, то мы можем свести представленный выше алгоритм к булевым матрицам: для каждого нетерминала заведём матрицу, такую что в ячейке стоит 1 тогда и только тогда, когда в исходной матрице в соответствующей ячейке содержится этот нетерминал. +Тогда перемножение пары таких матриц, соответствующих нетерминалам $A$ и $B$, соответствует построению путей, выводимых из нетерминалов, для которых есть правила с правой частью вида $A B$. + +\begin{example} +Представим в виде набора булевых матриц следующую матрицу: +\[ +T_0 = \begin{pmatrix} +\varnothing & \{A\} & \varnothing & \{B\} \\ +\varnothing & \varnothing & \{A\} & \varnothing \\ +\{A\} & \varnothing & \varnothing & \varnothing \\ +\{B\} & \varnothing & \varnothing & \varnothing \\ +\end{pmatrix} +\] + +Тогда: +\begin{alignat*}{7} +& &&T_{0\_A} &&= \begin{pmatrix} +0 & 1 & 0 & 0 \\ +0 & 0 & 1 & 0 \\ +1 & 0 & 0 & 0 \\ +0 & 0 & 0 & 0 \\ +\end{pmatrix} \ \ \ \ &&T_{0\_B} &&= \begin{pmatrix} +0 & 0 & 0 & 1 \\ +0 & 0 & 0 & 0 \\ +0 & 0 & 0 & 0 \\ +1 & 0 & 0 & 0 \\ +\end{pmatrix} +\end{alignat*} +Тогда при наличии правила $S \to A B$ в грамматике получим: +\[ +T_{1\_S} =T_{0\_A} \times T_{0\_B} = \begin{pmatrix} +0 & 0 & 0 & 0 \\ +0 & 0 & 0 & 0 \\ +0 & 0 & 0 & 1 \\ +0 & 0 & 0 & 0 \\ +\end{pmatrix} +\] +\end{example} + +Алгоритм же может быть переформулирован так, как показано в листинге~\ref{lst:cfpq_mtx_bool}. +Такой взгляд на алгоритм позволяет использовать для его реализации существующие высокопроизводительные библиотеки для работы с булевыми матрицами (например M4RI\footnote{M4RI --- одна из высокопроизводительных библиотек для работы с логическими матрицами на CPU. Реализует Метод Четырёх Русских. Исходный код библиотеки: \url{https://bitbucket.org/malb/m4ri/src/master/}. Дата посещения: 30.03.2020.}~\cite{DBLP:journals/corr/abs-0811-1714}) или библиотеки для линейной алгебры (например CUSP~\cite{Cusp}). + +\begin{algorithm} + \floatname{algorithm}{Listing} +\begin{algorithmic}[1] +\caption{Context-free path querying algorithm. Boolean matrix version} +\label{lst:cfpq_mtx_bool} +\Function{evalCFPQ}{$D=(V,E), G=(N,\Sigma,P)$} + \State{$n \gets$ |V|} + \State{$T \gets \{T^{A_i} \mid A_i \in N, T^{A_i}$ is a matrix $n \times n$, $T^{A_i}_{k,l} \gets$ \texttt{false}\} } + \ForAll{$(i,x,j) \in E$, $A_k \mid A_k \to x \in P$} + %\Comment{Matrices initialization} + %\For{$A_k \mid A_k \to x \in P$} + {$T^{A_k}_{i,j} \gets \texttt{true}$} + %\EndFor + \EndFor + \For{$A_k \mid A_k \to \varepsilon \in P$} + {$T^{A_k}_{i,i} \gets \texttt{true}$} + \EndFor + + \While{any matrix in $T$ is changing} + %\Comment{Transitive closure calculation} + \For{$A_i \to A_j A_k \in P$} + { $T^{A_i} \gets T^{A_i} + (T^{A_j} \times T^{A_k})$ } + \EndFor + \EndWhile +\State \Return $T$ +\EndFunction +\end{algorithmic} +\end{algorithm} + +С другой стороны, для запросов, выразимых в терминах грамматик с небольшим количеством нетерминалов, практически может быть выгодно представлять множества нетерминалов в ячейке матрицы в виде битового вектора следующим образом. +Нумеруем все нетерминалы с нуля, в векторе стоит 1 на позиции $i$, если в множестве есть нетерминал с номером $i$. +Таким образом, в каждой ячейке хранится битовый вектор длины $|N|$. +Тогда операция умножения определяется следующим образом: +\[v_1 \times v_2 = \{v \mid \exists (v,v_3) \in P, \textit{append}(v_1, v_2) \& v_3 = v_3\},\] где $\&$ --- побитовое \texttt{``и''}. + +Правила надо кодировать соответственно: продукция это пара, где первый элемент --- битовый вектор длины $|N|$ с единственной единицей в позиции, соответствующей нетерминалу в правой части, а второй элемент --- вектор длины $2|N|$, с двумя единицами кодирующими первый и второй нетерминалы. + +\begin{example} +Пусть $N = \{S, A, B\}$ и в грамматике есть продукция $S \to A B$. Тогда занумеруем нетерминалы $ (S, 0), (A, 1), (B, 2)$. Продукция примет вид $[1, 0, 0] \to [0, 1, 0, 0, 0, 1]$. Матрица $T_0$ примет вид (здесь ``$.$'' означает, что в ячейке стоит $[0,0,0]$): +\[ +T_0 = \begin{pmatrix} +. & [0,1,0] & . & [0,0,1] \\ +. & . & [0,1,0] & . \\ +[0,1,0] & . & . & . \\ +[0,0,1] & . & . & . \\ +\end{pmatrix} +\] + +После выполнения умножения получим: +\[ +T_1 = T_0 + T_0 \times T_0 = +\begin{pmatrix} +. & [0,1,0] & . & [0,0,1] \\ +. & . & [0,1,0] & . \\ +[0,1,0] & . & . & \cellcolor{lightgray}[1,0,0] \\ +[0,0,1] & . & . & . \\ +\end{pmatrix} +\] +\end{example} + + +На практике в роли векторов могут выступать беззнаковые целые числа. +Например, 32 бита под ячейки в матрице и 64 бита под правила (или 8 и 16, если позволяет количество нетерминалов в грамматике, или 16 и 32). +Тогда умножение выражается через битовые операции и сравнение, что довольно эффективно с точки зрения вычислений. + +Для небольших запросов такой подход к реализации может оказаться быстрее: в данном случае скорость зависит от деталей. +Минус подхода в том, что нет возможности использовать готовые библиотеки линейной алгебры без предварительной модификации. +Только если они не являются параметризуемыми и не позволяют задать собственный тип и собственную операцию умножения и сложения (иными словами, собственное полукольцо). +Такую возможность предусматривает, например, стандарт GraphBLAS\footnote{GraphBLAS --- открытый стандарт, описывающий набор примитивов и операций, необходимый для реализации графовых алгоритмов в терминах линейной алгебры. Web-страница проекта: \url{https://github.com/gunrock/graphblast}. Дата доступа: 30.03.2020.} и, соответственно, его реализации, такие как SuiteSparse\footnote{SuiteSparse --- это специализированное программное обеспечения для работы с разреженными матрицами, которое включает в себя реализацию GraphBLAS API. Web-страница проекта: \url{http://faculty.cse.tamu.edu/davis/suitesparse.html}. Дата доступа: 30.03.2020.}~\cite{Davis2018Algorithm9S}. + +Также стоит заметить, что при работе с реальными графами матрицы, как правило, оказываются разреженными, а значит необходимо использовать соответствующие представления матриц (CRS, покоординатное, Quad Tree~\cite{quadtree}) и библиотеки, работающие с таким представлениями. + +Однако даже при использовании разреженных матриц, могут возникнуть проблемы с размером реальных данных и объёмом памяти. +Например, для вычислений на GPGPU лучше всего, когда все нужные для вычисления матрицы помещаются на одну карту. +Тогда можно свести обмен данными между хостом и графическим сопроцессором к минимуму. +Если не помещаются все, то нужно, чтобы помещалась хотя бы тройка непосредственно обрабатываемых матриц (два операнда и результат). +В самом тяжёлом случае в памяти не удаётся разместить даже операнды целиком и тогда приходится прибегать к поблочному умножению матриц. + +Отдельной инженерной проблемой является масштабирование алгоритмов на несколько вычислительных узлов, как на несколько CPU, так и на несколько GPGPU. + +Важным свойством рассмотренного алгоритма является то, что описанные проблемы с объёмом памяти и масштабированием могут эффективно решаться в рамках библиотек линейной алгебры общего назначения, что избавляет от необходимости создавать специализированные решения для конкретных задач. + + +\section{От нескольких стартовых вершин} + +Статья:~\cite{Terekhov2021MultipleSourceCP} + +%\section{Вопросы и задачи} +%\begin{enumerate} +% \item Находить кратчайшие пути в графах, используя идеи из секции~\ref{Matrix-CFPQ}. +% \item Превратить граф, использующийся для CFPQ, в дерево. +% \item Реализовать предложенные идеи на различных архитектурах. +% \item Замерить производительность и расходы памяти по сравнению с существующими реализациями. +%\end{enumerate} diff --git a/tex/Multiple_Context-Free_Language_Reachability.tex b/tex/Multiple_Context-Free_Language_Reachability.tex new file mode 100644 index 0000000..cc81ba5 --- /dev/null +++ b/tex/Multiple_Context-Free_Language_Reachability.tex @@ -0,0 +1,401 @@ +\chapter{Поиск путей с ограничениями в терминах многокомпонентных контекстно-свободных языков} + +%В статтическом анализе кода --- ещё одна аппроксимация. Например, On. Есть ли точно описываемые задачи? + +%Алгоритм на матрицах + +Создание алгоритмов поиска путей с ограничениями в терминах многокомпонентных контекстно-свободных языков позволяет использовать более сложные графовые запросы. Такие алгоритмы могут найти применение в различных областях, например, в статическом анализе кода. На практике, одним из наиболее широко используемых КС-языков в задачах поиска путей в графе является язык Дика~\cite{zhang2013fast,kodumal2004set} правильных скобочных последовательностей. В частности, в статическом анализе программ этот язык используется для \textit{context-sensitive} или \textit{data-dependence} анализа~\cite{reps2000undecidability}. А именно, в \textit{context-sensitive} анализе моделируется сбалансированность вызовов и выходов из процедур с использованием открывающих и закрывающих скобок. Аналогично, в \textit{data-dependence} анализе используется какое-то одно сбалансированное свойство конструкторов языка, например, обращения к полям (т.е. чтения и записи~\cite{bastani2015specification,yan2011demand}), перенаправления указателей (т.е. ссылки и разыменования~\cite{zheng2008demand}) и т.д. Однако точный анализ, охватывающий два или более сбалансированных свойств является неразрешимой задачей~\cite{reps2000undecidability}. Например, \textit{context-sensitive} и \textit{data-dependence} анализ описывается шафлом языков Дика, и этот язык не является контекстно-свободным. Традиционный подход в таком случае заключается в аппроксимации решения с помощью алгоритмов КС-достижимости. Шафл языков Дика можно рассматривать как пересечение двух КС-языков. Однако КС-языки не замкнуты относительно операции пересечения~\cite{Hopcroft+Ullman/79/Introduction}. Поэтому приходится жертвовать точностью для одного из сбалансированных свойств, т.е. один из языков Дика для \textit{context-sensitive} или \textit{data-dependence} анализа аппроксимируется регулярным языком~\cite{huang2015scalable,sridharan2006refinement}. + +Однако для более точного анализа можно использовать и другие классы формальных языков. Например, \textit{линейные конъюнктивные языки} (LCL) могут применяться для \textit{context-sensitive} и \textit{data-dependence} анализа, причём демонстрируют значительные преимущества такого подхода в точности и масштабируемости~\cite{zhang2017context}. Таким образом, класс \textit{многокомпонентных контекстно-свободных языков} (MCFL) также может содержать языки, которые могут быть использованы для повышения точности решения некоторых задач статического анализа программ программного. Одним из кандидатов на место такого языка является язык $O_n$, который может моделировать согласованное количество открывающих и закрывающих скобок для \textit{context-sensitive} и \textit{data-dependence} анализа. Эти языки являются аппроксимациями шафлов языков Дика и, как известно, не являются контекстно-свободными. Например, $O_2=\{\omega \in \{a,\overline{a},b,\overline{b}\}^* \mid |\omega|_a=|\omega|_{\overline{a}} \wedge |w|_b=|w|_{\overline{b}}\}$. + + +Известно, что задача поиска путей с ограничениями в терминах многокомпонентных контекстно-свободных языков разрешима, поскольку MCFL замкнуты относительно пересечения с регулярными языками (т.е. с графами) и информация о достижимости может быть вычислена путем проверки полученного языка на пустоту, что является разрешимой задачей~\cite{seki1991multiple}. + +На практике хорошим приёмом для получения высокопроизводительных решений задач анализа графов является выражение наиболее критичных вычислений через операции линейной алгебры, например, через матричные операции~\cite{doi:10.1137/1.9780898719918}. Существуют эффективные алгоритмы парсинга для MCFL на основе линейной алгебры, использующие умножения булевых матриц~\cite{nakanishi1997efficient,cohen2016parsing} и способные лечь в основу новых алгоритмов MCFL-достижимости. Однако алгоритм в работе~\cite{cohen2016parsing} может быть применен только для некоторого подкласса многокомпонентных контекстно-свободных грамматик, называемого \textit{несбалансированными}. Поэтому далее в этой главе будет приведён алгоритм поиска путей с ограничениями в терминах многокомпонентных контекстно-свободных языков, основанный на алгоритме из работы~\cite{nakanishi1997efficient}. + + +\section{Нормальная форма MCFG}\label{normalformmcfg} +Сперва мы введём следующую нормальную форму для MCFG, которая позволяет решать задачу MCFL-достижимости с помощью операций линейной алгебры. + +\begin{definition} m-MCFG $G = (\Sigma, N, S, P)$ находится в \emph{нормальной форме}, если любое правило $p: A \rightarrow (\gamma_1, \dots, \gamma_{dim(A)}) \in P$ satisfies соответсвует одной из следующих форм. + \begin{itemize} + %\item $\forall i: 1 \leq i \leq d(A) \ \ \gamma_i \neq \varepsilon$ + \item $\forall i: |\gamma_i| = 1$ и $\gamma_i \in \Sigma \cup \{\varepsilon\}$. + \item $\forall i: \gamma_i \in N_c^*$, т.е. в правой части правила нету терминальных символов. Для простоты будем обозначать такие правила $p: A \rightarrow f(B_1, \dots, B_n)$, где $B_k \in N$. В таком случае необходимо, чтобы $n = 2$. В итоге, имеем правила вида $p: A \rightarrow f(B_1, B_2)$, где $B_1, B_2 \in N$. Для таких правил также должно выполнятся следующее. + \begin{itemize} + \item \textbf{Non-erasing condition}:$\forall i \in \{1,2\}, 1 \leq j \leq d(B_i)$ $B_i^j$ используется в $\gamma_k$ для некоторого $k$, + \item никакая пара символов $B^j, B^k$, являющихся компонентами одного и того нетерминала, не присутствует в правой части правила подряд, т.е. компоненты нетерминалов $B_1, B_2$ чередуются, + \item $\exists i: 1 \leq i \leq d(A) \ \ |\gamma_i| \geq 2$. + \end{itemize} + \end{itemize} +\end{definition} + +Согласно~\cite{nakanishi1997efficient}, справедлива следующая теорема. + +\begin{theorem}\label{thm:formofmcfg} + Для любой MCFG $G$ может быть построена MCFG $G'$ такая, что $L(G') = L(G)$ и $G'$ находится в описанной нормальной форме. +\end{theorem} + +Например, для $m = 1$ описанная нормальная форма соответствует ослабленной нормальной форме Хомского для КС-грамматик. + +Пусть имеется MCFG $G_1 = (\Sigma_1, N_1, S, P_1)$, где $\Sigma_1 = \{a,b,c,d\}$, $N_1 = \{S_, A, B\}$, $P_1 = \{$ +\begin{align*} + S^1 \rightarrow A^1 B^1 A^2 B^2 \\ + (A^1, A^2) \rightarrow (a,c) \\ + (B^1, B^2) \rightarrow (b,d) \\ + (B^1, B^2) \rightarrow (bB^1, dB^2) \\ + (A^1, A^2) \rightarrow (aA^1, cA^2) +\end{align*} +$\}.$ + +Такая грамматика порождает один из классических MCFL: $L(G_1) = \{a^nb^mc^nd^m \mid n,m \in \mathbb{N}\}$, который не является контекстно-свободным. + +Тогда грамматика $G'_1$ в нормальной форме может быть построена по грамматике $G_1$, где $L(G'_1) = L(G_1)$ и $N'_1 = \{S, S_1, S_2, A, B, C, D\}$, $P'_1 = \{$ +\begin{align*} + A^1 \rightarrow a \\ + B^1 \rightarrow b \\ + C^1 \rightarrow c \\ + D^1 \rightarrow d \\ + (S_1^1, S_1^2) \rightarrow (a,c) \\ + (S_2^1, S_2^2) \rightarrow (b,d) \\ + (S_1^1, S_1^2) \rightarrow (S_3^1, S_3^2 C^1) \\ + (S_3^1, S_3^2) \rightarrow (A^1 S_1^1, S_1^2) \\ + (S_2^1, S_2^2) \rightarrow (S_4^1, S_4^2 D^1) \\ + (S_4^1, S_4^2) \rightarrow (B^1 S_2^1, S_2^2) \\ + S^1 \rightarrow S_1^1 S_2^1 S_1^2 S_2^2 +\end{align*} +$\}.$ + +\section{Постановка задачи} +Сформулируем задачу MCFL-достижимости. + +\begin{definition} + Пусть дан помеченный граф $D = (V, E, \Sigma)$ и MCFL $L$. Тогда \emph{многокомпонентное контекстно-свободное отношение} для языка $L$ и графа $D$ --- это отношение $R_{D, L} \subseteq V \times V$: + \begin{equation*} \label{eq1} + \begin{split} + R_{D, L} = \{ &(v_0, v_n) \in V \times V \mid \\ &\ \exists \pi = ((v_0, l_1, v_1), \ldots, (v_{n-1}, l_n, v_n)) \in \pi(D): \\ + &\ l(\pi) \in L \}. + \end{split} + \end{equation*} +\end{definition} + +\begin{definition} + \emph{MCFL-достижимость} --- это задача нахождения многокомпонентных контекстно-свободных отношений $R_{D, L}$ для заданного помеченного графа $D$ и многокомпонентного контекстно-свободного языка $L$. +\end{definition} + +Другими словами, результатом решения задачи MCFL-достижимости является набор пар вершин, между которыми существует путь, образующий слово из заданного MCFL. + +Далее мы строим алгоритм для решения задачи MCFL-достижимости. + +\section{Матричный алгоритм MCFL-достижимости} +\label{sec:all-path-algo} +В этом разделе мы представляем алгоритм для решения задачи MCFL-достижимости, основанный на матричных операциях. + +\subsection{Алгоритм} + +\begin{definition} + \label{def:sets-end-alter} + Пусть имеется MCFG $G = (\Sigma, N, S, P)$ в нормальной форме. Тогда $\forall p: A \rightarrow f(B,C) \in P$ определим следующее: + \begin{itemize} + \item $end\_B(p) = \{2(i - 1)|$, если $B^i$ является самым левым символом в компоненте правой части правила $p\} \cup \{2(i - 1) + 1 |$, если $B^i$ является самым правым символом в компоненте правой части правила $p\}$, каждое из множеств упорядочено по компонентам нетерминала $A$, а внутри компонент --- слева направо; + \item $end\_C(p)$ определяется аналогично $end\_B(p)$, но со смещением $2dim(B)$, т.е. $end\_C(p)$ будет иметь элементы вида $2(i - 1) + 2dim(B)$ и $2(i - 1) + 1 + 2dim(B)$; + \item $end\_A(p)$ --- упорядоченное множество пар, у которых первый элемент соответсвует самому левом нетерминалу некоторой компоненты в правиле, а второй элемент --- самому правому, т.е. элементами пар являются элементы множеств $end\_B(p)$ и $end\_C(p)$, определённых выше; + \item $(2(i - 1)) \in alter\_B(p)$ или $(2(i - 1) + 1) \in alter\_B(p)$, если $(2(i - 1)) \notin end\_B(p)$ или $(2(i - 1) + 1) \notin end\_B(p)$, $\forall 1 \leq i \leq dim(B)$ соответственно; + \item $alter\_C(p)$ определяется аналогично $alter\_B(p)$, но со смещением $2dim(B)$. + \end{itemize} +\end{definition} + +Примечание: из описания нормальной формы следует, что $|alter\_B(p)| = |alter\_C(p)|$. + +Пусть имеется MCFG $G = (\Sigma, N, S, P)$ в нормальной форме и помеченный граф $D = (V, E, \Sigma)$, где $|V| = n$. Предлагаемый алгоритм представлен на листинге~\ref{lst:algomcfg}. + +На первом этапе алгоритм обрабатывает правила, в правой части которых есть только терминальные символы. Таким образом, алгоритм восстанавливает пути, которые можно получить за одно применение правила. Процедура $update$ представлена на листинге~\ref{lst:algomcfg2}. Она используется для обновления всех необходимых матриц для правил с нетерминалом $B$ в правой части новыми значениями в соответствии с найденными новыми путями. В процедуре обновления подсчитывается индекс с учетом множеств $end\_B(p)$, $end\_C(p)$, $alter\_B(p)$ и $alter\_C(p)$ и добавляется значение $True$ в соответствии с вычисленным индексом. + +\begin{algorithm}[H] + \floatname{algorithm}{Листинг} + \footnotesize + \begin{algorithmic}[1] + \caption{Алгоритм MCFL-достижимости} + \label{lst:algomcfg} + \State{$G = (\Sigma, N, S, P)$ --- MCFG, $D = (V, E, \Sigma)$ --- помеченный граф} + \State{$A_p, B_p, B_p\_new, C_p, C_p\_new$ $\gets$ нулевые булевы матрицы} + + \Procedure{$MCFL\_reachability$}{$G$, $D$} + \For{$p \in P : p = A \rightarrow (a_1, \dots, a_{d(A)})$} + \For{$(l_1, a_1, r_1), \dots, (l_{d(A)}, a_{d(A)}, r_{d(A)}) \in E$} + \State{$index \gets (l_1,r_1,l_2,\dots,r_{d(A)})$} + \State{$update(A, index)$} + \Comment{добавляем информацию о простых правилах} + \EndFor + \EndFor + + \For{$p \in P : p = A \rightarrow f(B,C)$} + \State{$B_p\_new, C_p\_new \gets B_p, C_p$} \Comment{все значения являются новыми на первой итерации} + \EndFor + + \While{матрицы $B_p$, $C_p$ изменяются} + \For{$p \in P : p = A \rightarrow f(B,C)$} \Comment{рассматриваем сложные правила} + \State{$A_p\_new \gets B_p\_new \times C_p + B_p \times C_p\_new$} \Comment{используем только новые значения} + \State{$B_p\_new, C_p\_new \gets$ пустые булевы матрицы} + + \For{$(i,j): A_p\_new[i,j] = True \wedge A_p[i,j] = False$} + \State{$A_p[i,j] \gets True$} + \State{$index \gets transform\_index(ToIndex(i), ToIndex(j), p)$} + \State{$update(A, index)$} + \Comment{добавляем новую информацию для нетерминала $A$} + \EndFor + \EndFor + \EndWhile + \State{$Res \gets$ пустая булева матрица} + \For{$p \in P : p = S \rightarrow f(B,C)$} + \Comment{вычисляем всю необходимую информацию для стартового нетерминала $S$} + \For{$(i,j): S_p[i,j] = True$} + \State{$index \gets transform\_index(ToIndex(i), ToIndex(j), p)$} + \State{$Res[index[0], index[1]] \gets True$} \Comment{размер индекса равен 2, так как $dim(S) = 1$} + \EndFor + \EndFor + \Return $Res$ + \EndProcedure + + + + \end{algorithmic} +\end{algorithm} + +В строке 6 листинга~\ref{lst:algomcfg} найдены $dim(A)$ путей длины 1 или 0, соответствующие компонентам правила $A \rightarrow (a_1, \dots, a_{dim(A)})$. То есть каждая пара $(l_i, r_i)$ --- это пара вершин, между которыми существует путь, порождённый из $i$-ой компоненты правила. Отметим два факта об этом индексе. Во-первых, в этом индексе есть $dim(A)$ пар, то есть количество элементов в нём чётное. Во-вторых, такой индекс можно закодировать как $(n+1)$-арное число ($n$ --- количество вершин в графе $D$). Второй факт позволяет использовать некоторый алгоритм $FromIndex$ (обратный ему $ToIndex$) для перевода такого числа в систему счисления с основанием $(n+1)$. Чётность числа элементов позволяет разделить индекс пополам и записать первую часть в индекс строки матрицы, а вторую --- в индекс столбца. Таким образом, факт о найденном пути для нетерминала запишем в квадратную булеву матрицу, разделив индекс пополам и переведя каждую часть в нужную систему счисления (пусть это будут числа $i$ и $j$), а в ячейку $(i, j)$ поместим значение $True$. + + +\begin{algorithm}[H] + \floatname{algorithm}{Листинг} + \footnotesize + \begin{algorithmic}[1] + \caption{Процедура обновления матриц} + \label{lst:algomcfg2} + + \Procedure{$update$}{$B$, $index$} + \Comment{обновляет матрицы для всех правил с $B$ в правой части} + \For{$p \in P : p = A \rightarrow f(B,C) $} + \State{$i_B, j_B \gets$ пустые списки} + \For{$end \in end\_B(p)$} + \State{$i_B.append(index[end])$} + \EndFor + + \For{$alter \in alter\_B(p)$} + \State{$j_B.append(index[alter])$} + \EndFor + \State{$B_p[FromIndex(i_B), FromIndex(j_B)] \gets True$} + \EndFor + + \For{$p: A\rightarrow f(C,B) $} + \State{$i_B, j_B \gets$ пустые списки} + \For{$alter \in alter\_B(p)$} + \State{$i_B.append(index[alter - 2d(C)])$} + \EndFor + + \For{$end \in end\_B(p)$} + \State{$j_B.append(index[end - 2d(C)])$} + \EndFor + \State{$B_p[FromIndex(i_B), FromIndex(j_B)] \gets True$} + \EndFor + \EndProcedure + + \end{algorithmic} +\end{algorithm} + +Далее, для каждого правила с нетерминалами в правой части алгоритм использует пять матриц. А именно, для правила $p$ вида $A \rightarrow f(B, C)$ алгоритм поддерживает матрицу $B_p$, в которой хранится результат, учитывающий множества из определения~\ref{def:sets-end-alter} для нетерминала $B$, а также матрицу $B_p\_new$, в которой хранится результат, учитывающий множества, полученные только на предыдущем шаге. Аналогично для нетерминала $C$. Также информация о найденных путях, соответствующих данному правилу, хранится в матрице $A_p$ с учетом множества $end\_A(p)$. А после обработки правил с терминальными символами в правой части необходимо добавить новые результаты в поддерживаемые матрицы. Именно это и делает алгоритм в строках 8-9. + +Далее, в строке 12 алгоритм вычисляет новые пути в графе, используя четыре матрицы для нетерминалов из правой части правил. При этом алгоритм обновляет матрицы $B_p\_new$ и $C_p\_new$ для хранения только тех новых значений, которые были добавлены на данной итерации. Также алгоритм записывает только новые значения в матрицу $A_p$ для нетерминала $A$ и распространяет новые результаты среди всех матриц для нетерминала $A$ в правых частях других правил. + +Алгоритм продолжает работу, используя цикл в строках 10-17, пока на текущей итерации появилось хотя бы одно новое значение. На последнем шаге алгоритм собирает значения из всех правил, где в левой части есть стартовый нетерминал, и заносит их в матрицу $Res$ для получения результата MCFL-достижимости. Индексы должны быть пересчитаны с помощью процедуры $transform\_index$, представленной на листинге~\ref{lst:algomcfg3}. + +\begin{algorithm}[H] + \floatname{algorithm}{Листинг} + \footnotesize + \begin{algorithmic}[1] + \caption{Процедура для преобразования индекса} + \label{lst:algomcfg3} + + \Procedure{$transform\_index$}{$i$, $j$, $p$} + \Comment{преобразует индексы $i$ и $j$ в соответствии с множеством $end\_A(p)$} + \State{$A \gets $ нетерминал из левой части правила $p$} + \State{$index \gets$ пустой список} + \For{$(end_l, end_r) \in end\_A(p)$} + \If{$end_l < 2d(B)$} + \State{$pos \gets$ позиция $end_l$ в $end\_B(p)$} \State{$index.append(i[pos])$} + \Else + \State{$pos \gets$ позиция $end_l$ в $end\_C(p)$} \State{$index.append(j[pos])$} + \EndIf + + \If{$end_r < 2d(B)$} + \State{$pos \gets$ позиция $end_r$ в $end\_B(p)$} \State{$index.append(i[pos])$} + \Else + \State{$pos \gets$ позиция $end_r$ в $end\_C(p)$} \State{$index.append(j[pos])$} + \EndIf + \EndFor + \Return $index$ + \EndProcedure + + \end{algorithmic} +\end{algorithm} + +Матрица $Res$, полученная в результате работы алгоритма, представленного на листинге~\ref{lst:algomcfg}, является ответом на задачу $MCFL$-достижимости. + + +% Consider a $2m$ - dimensional matrix $Res$ for $A \in N$ of size $(n + 1)^{2m}$ ($2m$ is Cartesian product degree). For convenience of notation, we assume that $Res[l_1, r_1, l_2, r_2, \dots, l_{d(A)}, r_{d(A)}, 0, \dots, 0] = Res[l_1, r_1, l_2, r_2, \dots, l_{d(A)}, r_{d(A)}]$. + +% Denote matrix $Res$ for $A \in N$ like $Res_A$. + +% Boolean matrix $Res_A$ indexing can be conveniently represented as $(l_1, r_1,$ $\dots, l_{d(A)}, r_{d(A)})$. This representation denote $(n+1)-ary$ number, what can be useful in the implementation. We call \emph{FromIndex} the algorithm obtaining a number from an index for matrix $Res_A$ and \emph{ToIndex} inverse to it. Matrix $Res_A$ can be represented as a square matrix of size $FromIndex((n+1, \dots, n+1)) \times FromIndex((n+1, \dots, n+1))$ ($|(n+1, \dots, n+1)|$ = $2m$), since each index of the matrix $Res_A$ has an even number of elements. That is, we can halve the index and store the left side in the row index, and the right side in the column index. If necessary, we can get the full index by concatenating the results of \emph{ToIndex}. + +% We construct the algorithm in such a way that it is true that $\forall i: 1 \leq i \leq d(A) \ \ \exists \pi_i$ --- path between $l_i$ and $r_i: A \xLongrightarrow[G]{*} (l(\pi_1), \dots, \pi_{d(A)})$ iff $Res[l_1, r_1, \dots, l_{d(A)}, r_{d(A)}] = True$. We call it \emph{main condition} of the algorithm. + +% The algorithm consists of two main steps. The first step is to process the terminating rules of $G$. For this consider $p: A \rightarrow (a_1, \dots, a_{d(A)}) \in P$. To satisfy the main condition, set $Res[l_1, r_1, \dots$ $, l_{d(A)}, r_{d(A)}] = True$ iff $(l_1, a_1, r_1), \dots, (l_{d(A)}, a_{d(A)} r_{d(A)}) \in E$ (all combinations). + +% The second step is to consider non-terminating rules. For this consider $p: A \rightarrow f(B,C) \in P$. + +% Construct two boolean matrices $B_p$ and $C_p$ from $Res_B$, $end\_B(p)$, $alter\_B(p)$, $Res_C$, $end\_C(p)$ and $alter\_C(p)$. + +% Describe construction $B_p$. Consider $\forall i_{res} = (l_1, r_1, \dots, l_{d(B)}, r_{d(B)}): Res_B[l_1, r_1, \dots, l_{d(B)}, r_{d(B)}] = True$ and construct index by taking the elements of $i_{res}$ at the positions pointed by the the elements $end\_B(p)$ and putting them in the order of consideration of the elements $end\_B(p)$. Denote the resulting index $i_B$. Similarly, we construct $j_B$ using $alter\_B(p)$. At the end we put $B_p[FromIndex(i_B)$ $, FromIndex(j_B)] = True$. + +% Similarly, we construct $C_p$ but in the process of construction consider the values of $end\_C(p)$ and $alter\_C(p)$ reduced by $2d(B)$. We cannot store the values from these sets immediately equal to the positions for the index, since it is necessary to distinguish them from the value from the sets $end\_B(p)$, $alter\_B(p)$. + +% Further, we calculate $A_p = B_p \times C_p$. + +% At the end, update the Boolean matrix $Res_A$ using $A_p$. To do this, consider $\forall (i,j): A_p[i,j] = True$, compute $i_A = ToIndex(i)$ and $j_A = ToIndex(j)$. We get the index for the matrix $Res_A$ by putting the elements $i_A$ and $j_A$ in the right positions using ordered pairs from $end\_A$. + + +\subsection{Пример} + +Рассмотрим некоторые шаги алгоритма на примере. В качестве входных данных возьмем граф $D_1$, представленный на рисунке~\ref{fig:example_input_graph_mcfg}, и многокомпонентную контекстно-свободную грамматику $G'_1$ из раздела~\ref{normalformmcfg}. + +\begin{figure}[h] + \centering + \resizebox{\columnwidth}{!}{\begin{tikzpicture}[shorten >=1pt,auto] + \node[state] (q_0) {$1$}; + \node[state] (q_1) [right=of q_0] {$2$}; + \node[state] (q_2) [right=of q_1] {$3$}; + \node[state] (q_3) [right=of q_2] {$4$}; + \node[state] (q_4) [right=of q_3] {$5$}; + \path[->] + (q_0) edge[bend left,above] node {$a$} (q_1) + (q_1) edge[bend left,above] node {$b$} (q_2) + (q_2) edge[bend left,above] node {$c$} (q_3) + (q_3) edge[bend left,above] node {$d$} (q_4) + (q_4) edge[bend left,below] node {$a$} (q_3) + (q_3) edge[bend left,below] node {$b$} (q_2) + (q_2) edge[bend left,below] node {$c$} (q_1) + (q_1) edge[bend left,below] node {$d$} (q_0); + \end{tikzpicture} + } + \caption{Входной граф $D_1$} + \label{fig:example_input_graph_mcfg} +\end{figure} + +На первом шаге алгоритм обрабатывает простые правила $G_1$ (строки 4-7 в листинге~\ref{lst:algomcfg}). Также алгоритм обновляет матрицы с суффиксом $\_new$ для нетерминалов в правых частях каждого правила. Рассмотрим, например, как выглядят после этих обновлений матрицы $B_p\_new$ и $C_p\_new$ для правила $S^1 \rightarrow S_1^1 S_2^1 S_1^2 S_2^2$. Для этого правила алгоритм использует множества из определения~\ref{def:sets-end-alter}, которые выглядят следующим образом. + +\begin{center} + \begin{itemize} + \item $end\_B = \{0\}$ + \item $alter\_B = \{1,2,3\}$ + \item $end\_C = \{7\}$ + \item $alter\_C = \{4,5,6\}$ + \item $end\_A = \{(0, 7)\}$ + \end{itemize} +\end{center} + +\begin{center} + $B_p = B_p\_new = $ {\footnotesize + \bordermatrix{\text{ }&(2,3,2)&(2,3,4)&(4,3,2)&(4,3,4)\cr + (1)&True&True&.&.\cr + (5)&.&.&True&True} + } +\end{center} + + +\begin{center} + $C_p = C_p\_new = $ $C_p$ = \bordermatrix{\text{ }&(1)&(5)\cr + (2,3,2)&True&.\cr + (4,3,2)&.&True\cr + (2,3,4)&True&.\cr + (4,3,3)&.&True} +\end{center} + + + +% At the first step, the algorithm process the terminal rules of $G_1$ (row 5-8 in listing~\ref{lst:algomcfg}). Finally put $\forall N \in \{A,B,C,D\}, x \in \Sigma: N \rightarrow x \in P,$ $Res_N[i,j] = True$, where $(i, x, j) \in E$ and $\forall N \in \{S_1, S_2\}: (N^1, N^2) \rightarrow (x_1, x_2) \in P,$ $Res_N[i_1,j_1,i_2,j_2] = True$, where $(i_1, x_1, j_1), (i_2, x_2, j_2) \in E$. At the end of this step, the matrix $Res$ looks like this. We present the matrix $Res$ without boolean decomposition for brevity. As noted above, the indexing of the original matrix $Res_N$ for some nonterminal N can be obtained by concatenating the row and column index. For example, if $i=(1,2)$ and $j = (3,4)$ then $index = (1,2,3,4)$. + +% {\footnotesize + % \bordermatrix{\text{ }&(1)&(2)&(3)&(4)&(5)&(2,1)&(3,2)&(3,4)&(4,5)\cr + % (1)&.&\{A\}&.&.&.&.&.&.&.\cr + % (2)&\{D\}&.&\{B\}&.&.&.&.&.&.\cr + % (3)&.&\{C\}&.&\{C\}&.&.&.&.&.\cr + % (4)&.&.&\{B\}&.&\{D\}&.&.&.&.\cr + % (5)&.&.&.&\{A\}&.&.&.&.&.\cr + % (1,2)&.&.&.&.&.&.&\{S_1\}&\{S_1\}&.\cr + % (2,3)&.&.&.&.&.&\{S_2\}&.&.&\{S_2\}\cr + % (4,3)&.&.&.&.&.&\{S_2\}&.&.&\{S_2\}\cr + % (5,4)&.&.&.&.&.&.&\{S_1\}&\{S_1\}&.} + % } + +На втором шаге алгоритм обрабатывает правила с нетерминальными символами (строки 10-17 в листинге~\ref{lst:algomcfg}). Рассмотрим правило с нетерминалом $S$ в левой части. Сначала алгоритм перемножает матрицы $B_p$, $B_p\_new$, $C_p$ и $C_p\_new$ в указанном порядке (строка 12 в листинге~\ref{lst:algomcfg}). В результате вычисляется матрица $A_p\_{new}$ следующего вида. Обратите внимание, что строки и столбцы с нулевыми значениями мы опускаем. + +\begin{center} + $A_p\_new$ = \bordermatrix{\text{ }&(1)&(5)\cr + (1)&True&True\cr + (5)&True&True} +\end{center} + +Далее алгоритм попытается распространить информацию о найденных путях и рассмотреть другие правила. Однако далее никаких других путей получено не будет. На последнем этапе алгоритм строит матрицу для стартового нетерминала, которая в данном случае будет совпадать с предыдущей матрицей. + +\begin{center} + $Res = A_p$ = \bordermatrix{\text{ }&(1)&(5)\cr + (1)&True&True\cr + (5)&True&True} +\end{center} + +Таким образом, алгоритм получил информацию о том, что существуют пути, удовлетворяющие грамматике $G_1$, из вершины 1 в 5, из 5 в 1, из 1 в 1 и из 5 в 5. Поэтому многокомпонентное контекстно-свободное отношение $R_{D_1, L(G_1)} = \{(1, 5), (5, 1), (1, 1), (5, 5)\}$. + +% First, the algorithm builds the matrix $B_p$ and $C_p$ (row 8-27 in listing~\ref{lst:algomcfg}, using the procedure $build\_B_pC_p$). For example, considering $i=(1,2)$ and $j=(3,4)$, where $Res_{S_1}[i,j] = True$, in this case initializes $B_p[(1), (2,3,4)] = True$, since $end\_B = \{0\}$ and $alter\_B = \{1,2,3\}$, that is, using the indexing of the original matrix $Res_{S_1}$ $index = (1,2,3,4)$, the first set dictates what needs to be chosen $(1)$ as the index row of the matrix $B_p$ (since $(1)$ is at position 0 in $index$). The second set dictates what needs to be chosen $(2,3,4)$ as the index column for the same reasons. + +% $B_p$ = \bordermatrix{\text{ }&(2,3,2)&(4,3,2)&(2,3,4)&(4,3,3)\cr + % (1)&True&.&True&.\cr + % (5)&.&True&.&True} + +% $C_p$ = \bordermatrix{\text{ }&(1)&(5)\cr + % (2,3,2)&True&.\cr + % (4,3,2)&.&True\cr + % (2,3,4)&True&.\cr + % (4,3,3)&.&True} + +% Second, the algorithm multiply $B_p$ and $C_p$. + +% $A_p = B_p \times C_p$ = \bordermatrix{\text{ }&(1)&(5)\cr + % (1)&True&True\cr + % (5)&True&True} + +% At the end of the iteration, the matrix $Res_S$ is updated (row 41-59 in listing~\ref{lst:algomcfg}). At this step, it is known that $i$ is obtained using the set $end\_B$ and j using the set $end\_C$, where $A_p[i,j]=True$. The algorithm consider $(end_l, end_r) = (0,7)$. Since $end_l < 2d(B) = 4$ it takes the position of $end_l$ in $end\_B$ ($end\_B$ is ordered set) and puts in $index$ the value at that position (in this case $pos = 0$) in $i_A$ (which was received in the row 42). Similarly for $end_r$. + +% $Res_S =$ \bordermatrix{\text{ }&(1)&(5)\cr + % (1)&True&True\cr + % (5)&True&True} + +\subsection{Корректность и сложность} +Аналогично доказательству корректности матричного алгоритма КС-достижимости, можно показать, что следующая теорема справедлива по индукции на высоты деревьев вывода строк, образованных найденными путями в графе. + +\begin{theorem}\label{thm:correctness} + Пусть даны MCFG $G = (\Sigma, N, S, P)$ в нормальной форме и помеченный граф $D =(V, E, \Sigma)$. Пусть $Res$ --- матрица, полученная в результате работы алгоритма (листинг~\ref{lst:algomcfg}). Тогда $(v_0, v_n) \in R_{D,L(G)}$ тогда и только тогда, когда $Res[v_0,v_n] = True$. +\end{theorem} + +Наиболее трудоёмкой частью алгоритма является вычисление новых значений операцией $B_p \times C_p$ в строке 13. Далее мы оценим время, необходимое для вычисления $B_p \times C_p$. Предположим, что размеры булевых матриц $B_p$ и $C_p$ равны $(n+1)^q \times (n+1)^r$ и $(n+1)^r \times (n+1)^s$, соответственно. Тогда для каждого правила $p: A \rightarrow f(B,C)$ мы определяем \textit{степень} этого правила $e(p) = dim(A) + dim(B) + dim(C)$. Также определим \textit{multiplication unit} правила $p$ следующим образом. + +\begin{definition} + Пусть дана MCFG $G = (\Sigma, N, S, P)$ в нормальной форме. Тогда для каждого правила $p: A \rightarrow f(B,C)$ оперделим число $i(p)$, называемое \textit{multiplication unit} правила p, как $dim(A) + dim(B) + dim(C) - 2 \cdot max\{dim(A), dim(B), dim(C)\}$. +\end{definition} + +%According to~\cite{nakanishi1997efficient}, the $B_p \times C_p$ operations can be computed in $O(n^{e(p) - 0.624i(p)})$. Now we must estimate the number of iterations of the algorithm in listing~\ref{lst:algomcfg}. In~\cite{nakanishi1997efficient} the algorithm solves the MCFL recognition problem, and only $n$ iterations are needed. Thus, the MCFL recognition algorithm in~\cite{nakanishi1997efficient} computes the result in time $O(n^{e(p) - 0.624i(p) + 1})$. In our MCFL-reachability algorithm, we may need to make more iterations. The matrices $B_p$ (or $C_p$) can only change if a new tuple of paths $(\pi_1, \ldots, \pi_{d(B)})$ was found, such that $B \xLongrightarrow[G]{*} (l(\pi_1), \dots, l(\pi_{d(B)}))$. Such tuples of paths are described in the algorithm using the indices $(l_1, r_1, l_2, \ldots, r_{d(B)})$ where $\forall 1 \leq i \leq d(B)$, $\pi_i$ --- is a path from vertex $l_i$ to vertex $r_i$. In the worst case, exactly one new index will appear on each iteration. Thus, the number of iterations does not exceed the number of distinct indices. Let $m$ be the dimension of the MCFG $G$. Then the number of distinct indices is $O(n^{2m})$. Therefore, the following theorem holds. + +\begin{theorem}\label{thm:complexity} + Пусть дана m-MCFG $G = (\Sigma, N, S, P)$ в нормальной форме и помеченный граф $D =(V, E, \Sigma)$. Пусть $p'$ --- правило грамматики, для которого $e(p') - 0.624i(p') = max\{e(p) - 0.624i(p) \mid p\in P\}$, и пусть $e' = e(p')$, $i' = i(p')$. Тогда алгоритм, представленный на листинге~\ref{lst:algomcfg}, завершит работу за $O(|V|^{e' - 0.624i' + 2m})$. +\end{theorem} + +Это первое наивное ограничение временной сложности для проблемы MCFL-достижимости. Например, для грамматики $G'_1$ из раздела~\ref{normalformmcfg}, $e' = 5$, $i' = 1$, а $m = 2$. Таким образом, граница временной сложности для этой грамматики составляет $O(|V|^{8,376})$. Однако $O(n^{2m})$ итераций может быть достигнуто только на специальных искусственных графах, а обычно на реальных графах количество итераций невелико. Кроме того, известны приёмы улучшения такой оценки сложности путём рекурсивного умножения подматриц~\cite{Valiant:1975:GCR:1739932.1740048}. Наконец, оценка сложности может быть улучшеноа за счёт учёта разреженности матриц и исползования операций над разреженными матрицами. diff --git a/tex/Multiple_Context-Free_Languages.tex b/tex/Multiple_Context-Free_Languages.tex new file mode 100644 index 0000000..95002a8 --- /dev/null +++ b/tex/Multiple_Context-Free_Languages.tex @@ -0,0 +1,207 @@ +\chapter[Многокомпонентные контекстно-свободные языки]{Многокомпонентные контекстно-свободные языки\footnote{Мы дадим лишь базовые определения и приведём краткий обзор данного класса. В качестве отправной точки для более детального изучения можно порекомендовать материалы, подготовдленные Сильваном Салвати (Sylvain Salvati): \url{https://www.labri.fr/perso/salvati/downloads/cours/esslli/}}} + +\textit{Многокомпонентны контекстно-свободные языки} (и соответствующий класс грамматик) --- это строгое расширение контекстно-свободных языков (грамматик), обладающее рядом свойств !!! + +\begin{definition} + \textit{m-MCFG(r)} это четвёрка $\langle \Sigma, N, S, P \rangle$ + \begin{itemize} + \item $\Sigma$ --- терминальный алфавит + \item $N$ --- нетерминальные символы. Максимальный ранг (арность, местность) равен $m$. + \item $S$ --- стартовый нетерминальный символ ранга 1 + \item $P$ --- множество правил вида + $$ + A(s_1,\ldots,s_k) \leftarrow B_1(x_1^1,\ldots,x_{k_1}^1), \ldots, B_n(x_1^n,\ldots,x_{k_n}^n) + $$ + \begin{itemize} + \item $A$ --- нетерминал ранга $k$, $B_i$ --- нетерминалы ранга $k_i$, $n \leq r$ + \item Все $x^i_j$ попарно различны (переменные) + \item $s_i \in (\Sigma \cup X)^*, X = \bigcup_{i=1}^n \bigcup_{j=1}^{k_i} {x^i_j}$ + \end{itemize} + \end{itemize} + \end{definition} + +Приведём примеры многокомпонентных контекстно-свободных грамматик. Для начал рассмотрим грамматики для известных нам контекстно-свободных языков: +\begin{itemize} + \item язык вложенных скобок (\ref{grm:nestedbrs_cfg} и \ref{grm:nestedbrs_mcfg}, соответственно);\\ + \begin{minipage}[t]{0.4\textwidth} + \begin{align}\label{grm:nestedbrs_cfg} + S &\to a S b \nonumber \\ + S &\to \varepsilon + \end{align} + \end{minipage} + ~ + \begin{minipage}[t]{0.2\textwidth} + \end{minipage} + ~ + \begin{minipage}[t]{0.4\textwidth} + \begin{align}\label{grm:nestedbrs_mcfg} + S(axb) & \leftarrow S(x) \nonumber \\ + S(\varepsilon) & \leftarrow + \end{align} + \end{minipage} + \item язык Дика на одном типе скобок(\ref{grm:d1_cfg} и \ref{grm:d1_mcfg}, соответственно).\\ + \begin{minipage}[t]{0.4\textwidth} + \begin{align}\label{grm:d1_cfg} + S &\to a S b S \nonumber \\ + S &\to \varepsilon + \end{align} + \end{minipage} + ~ + \begin{minipage}[t]{0.2\textwidth} + \end{minipage} + ~ + \begin{minipage}[t]{0.4\textwidth} + \begin{align}\label{grm:d1_mcfg} + S(ax_1bx_2) & \leftarrow S(x_1), S(x_2) \nonumber \\ + S(\varepsilon) & \leftarrow + \end{align} + \end{minipage} + +\end{itemize} + +Теперь рассмотрим грамматику для языка $L = \{a^nc^mb^nd^m \mid n \in \mathbb{N}, m \in \mathbb{N} \}$, не являющегося контекстно-свободным: + \begin{align*} + S(x_1 y_1 x_2 y_2) & \leftarrow P(x1,x2),Q(y_1,y_2) \\ + P(ax_1, bx_2) & \leftarrow P(x_1,x_2) \\ + P(\varepsilon,\varepsilon) &\leftarrow \\ + Q(cx_1, dx_2) & \leftarrow Q(x_1,x_2) \\ + Q(\varepsilon,\varepsilon) &\leftarrow + \end{align*} + + + + + + Расширения MCFG + \begin{enumerate} + \item \textbf{PMCFG} (parallel MCFG) + $$ + A(x, ax) \leftarrow B(x) + $$ + + \item + $$ + A(x) \leftarrow B(x),C(x) + $$ + \item \textbf{simpleLMG} + $$ + A(x, x) \leftarrow B(x),C(x) + $$ + \end{enumerate} + + $MCFL \varsubsetneq PMCFL \varsubsetneq simpleLMG = P$ + + $\{a^{2^n} \mid n\geq 0\} \in PMCFL - MCFL $ + + $S(xx) \leftarrow S(x)$ + + $S(a) \leftarrow $ + + Разновидности MCFG + \begin{itemize} + \item \textbf{Неудаляющая} --- $\forall i \in \{i,\ldots,n\}, j\in \{1,\ldots,k_i\} \ x^i_j \text{ используется в } s_1,\ldots,s_k $ + \item \textbf{Непереставляющая} --- $\forall i \in \{i,\ldots,n\}, j,k\in \{1,\ldots,k_i\}, \text{если} j < k, \text{ то } x^i_j \text{ встречается в } s_1,\ldots,s_k \text{ перед } x^i_k$ + \item \textbf{Well-nested} --- неудаляющая, непереставляющая и + \begin{align*} + &\forall i,i' \in \{i,\ldots,n\}, i\neq i', \\ + &j\in \{1,\ldots,k_i-1\}, j\in \{1,\ldots,k_{i'}-1\},\\ + &s_1\cdots s_k \notin (\Sigma \cup X)^* x^i_j (\Sigma \cup X)^* x^{i'}_{j'} (\Sigma \cup X)^* x^i_{j+1} (\Sigma \cup X)^* x^{i'}_{j'+1}(\Sigma \cup X)^* + \end{align*} + \end{itemize} + + Пример well-nested MCFG + \begin{itemize} + %\item[\faCheck] [\faTimes] + \item[\faCheck] $A(\highlight[pink]{x_1},\highlight{z_1,z_2},\highlight[pink]{x_2},\highlight[green]{y_1,y_2,y_3},\highlight[pink]{x_3}) \leftarrow B(x_1,x_2,x_3),C(y_1,y_2,y_3),D(z_1,z_2)$ + \item[\faTimes] $A(\highlight{z_1},\highlight[pink]{x_1},\highlight[green]{y_1},\highlight[pink]{x_2},\highlight{z_2},\highlight[green]{y_2},\highlight[pink]{x_3},\highlight[green]{y_3}) \leftarrow B(x_1,x_2,x_3),C(y_1,y_2,y_3),D(z_1,z_2)$ + \end{itemize} + + \begin{theorem}[genaral MCFG] + \begin{align*} + &\forall L \in \text{m-MCFG } \exists n \geq 1 \ \underline{\boldsymbol{\exists} z} \in L (|z| \geq n) \\ + &\exists \text{ разбиение } z=u_1 v_1 w_1 s_1 u_2 \ldots u_m v_m w_m s_m u_{m+1}, \Sigma|v_js_j| \geq 1 \\ + &\forall i \geq 0: z_i = u_1 v_1^i w_1 s_1^i u_2 \ldots u_m v_m^i w_m s_m^i u_{m+1} \in L + \end{align*} + \end{theorem} + + \begin{theorem}[well-nested MCFG] + \begin{align*} + &\forall L \in \text{m-wnMCFG } \exists n \geq 1 \ \underline{\boldsymbol{\forall} z} \in L (|z| \geq n) \\ + &\exists \text{ разбиение } z=u_1 v_1 w_1 s_1 u_2 \ldots u_m v_m w_m s_m u_{m+1}, \Sigma|v_js_j| \geq 1 \\ + &\forall i \geq 0: z_i = u_1 v_1^i w_1 s_1^i u_2 \ldots u_m v_m^i w_m s_m^i u_{m+1} \in L + \end{align*} + \end{theorem} + + Иерархии внутри MCFL + \begin{theorem} + $(m*(k-1))$-$MCFL(r-k) \subseteq m$-$MCFL(r) $ если $1 \leq k \leq r - 2$ + \end{theorem} + + \begin{theorem}[Seki et al] + $L_{m+1} = \{a_1^nb_1^n\cdots a_{m+1}^n b_{m+1}^n \mid n\in \mathbb{N}\}$ является $(m+1)$-$MCFL(1)$, но не является $m$-$MCFL(r)$ ни для какого $r$ + \end{theorem} + + +\begin{figure} + \includegraphics[width=\textwidth]{figures/mcfg/mcfg.pdf} + \label{fig:mcfg_hierarachy_1} + \caption{Иерархия по $m$} +\end{figure} + + Иерархия для $m=1$ + \begin{theorem} + 1-MCFL = CFL + \end{theorem} + + \begin{theorem} + 1-MCFL(1) $\varsubsetneq$ 1-MCFL(2) + \end{theorem} + + \begin{theorem} + 1-MCFL($r$) = 1-MCFL($r+1$), $r\geq2$ + \end{theorem} + + Иерархия для $m=2$ + \begin{theorem}[Ramow, Satta] + 2-MCFL(2) = 2-MCFL(3) + \end{theorem} + + \begin{theorem} + Если $m>2$ или $r>2$, то m-MCFL(r) $\varsubsetneq$ m-MCFL(r+1) + \end{theorem} + +\begin{figure} + \includegraphics[width=\textwidth]{figures/mcfg/mcfg_2.pdf} + \label{fig:mcfg_hierarachy_2} + \caption{Иерархия по $r$} +\end{figure} + + +Про MIX и $O_n$ + +\begin{itemize} + \item $mix = \{\omega \in \{a,b\}^* \mid |\omega|_a = |\omega|_b \}$ --- контекстно-свободный язык + + \item $MIX = \{\omega \in \{a,b,c\}^* \mid |\omega|_a = |\omega|_b = |\omega|_c\}$ --- MCFL? Хотелось верить, что нет + \begin{itemize} + \item \href{https://hal.inria.fr/inria-00564552/document}{MIX is a 2-MCFL and the word problem in $\mathbb{Z}^2$ is solved by a third-order collapsible pushdown automaton, Sylvain Salvati, 2011}~\cite{salvati:inria-00564552} + \end{itemize} + \item $O_2=\{\omega \in \{a,\overline{a},b,\overline{b}\}^* \mid |\omega|_a=|\omega|_{\overline{a}} \wedge |w|_b=|w|_{\overline{b}}\}$ + \item $O_n=\{\omega \in \{a_1,\overline{a_1},a_2,\overline{a_2},\ldots,a_n,\overline{a_n}\}^* \mid |\omega|_{a_1}=|\omega|_{\overline{a_1}} \wedge |w|_{a_2}=|w|_{\overline{a_2}} \wedge \cdots \wedge |w|_{a_n}=|w|_{\overline{a_n}}\}$ + \item $MIX_n = \{\omega \in \{a_1,\ldots,a_n\}^* \mid |\omega|_{a_1} = |\omega|_{a_2} =\cdots = |\omega|_{a_n}\}$ + \item $MIX_n$ регулярно эквивалентен $O_n$ (существует алгоритм построения грамматики одного языка по грамматике другого) + \begin{itemize} + \item \href{https://hal.archives-ouvertes.fr/hal-01771670/document}{$O_n$ is an n-MCFL, Sylvain Salvati, 2018}~\cite{GEBHARDT202241} + \end{itemize} + \end{itemize} + + + \begin{itemize} + \item Варианты леммы о накачке + \item Представимость конкретных языков + \begin{itemize} + \item Многомерный язык Дика: \href{https://link.springer.com/chapter/10.1007/978-3-662-59620-3_5}{Towards a 2-Multiple Context-Free Grammar for the 3-Dimensional Dyck Language, Konstantinos Kogkalidis, Orestis Melkonian, 2019}~\cite{10.1007/978-3-662-59620-3_5} + \item Шафл языков Дика: \href{https://dl.acm.org/doi/10.1145/3093333.3009848}{Context-sensitive data-dependence analysis via linear conjunctive language reachability, Qirun Zhang, Zhendong Su et al, 2017}~\cite{10.1145/3009837.3009848} + \end{itemize} + \end{itemize} + diff --git a/tex/RPQ.tex b/tex/RPQ.tex new file mode 100644 index 0000000..7eb1ed1 --- /dev/null +++ b/tex/RPQ.tex @@ -0,0 +1,669 @@ +\chapter{Поиск путей с регулярными ограничениями} + +\section{Достижимость между всеми парами вершин} + +Через тензорное произведение. + +Классическое построение пересечения автоматов строит их тензорное произведение. + +Так как мы хотим отвечать ещё и на вопрос о достижимости, что нам надо ещё и транзитивное замыкание посчитать. + +\section{Достижимость с несколькими источниками} + +Достижимость от нескольких стартовых вершин через обход в ширину, основанный на линейной алгебре~\cite{9286186}. + +Идея алгоритма основана на одновременном обходе в ширину графа и конечного автомата, построенного по грамматике. + +В классической версии обхода в ширину, основанного на линейной алгебре, используется вектор, куда записывается фронт обхода графа. +Так, один раз перемножая этот вектор на матрицу смежности графа, можно совершать один шаг в обходе графа. +Покажем на примере, как данный метод может быть использован, когда мы накладываем дополнительные ограничения в виде регулярного языка на путь в графе. + +Для этого, во-первых, предъявим булевые представления для матриц смежности графа и автомата для регулярного языка. Затем, введем специальную блочно--диагональную матрицу +для синхронизации обхода в ширину по двум матрицам смежности. Далее, попробуем наивно реализовать обход в ширину, и посмотрим, почему наивная реализация +может выдавать некорректный результат. +После этого перейдем к реализации обхода в ширину более продвинутым методом, который решает проблему наивного подхода. + +\begin{example} + Возьмём следующий граф. + \begin{center} + \label{input_rpq} + \begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] + \node[state] (q_0) {$1$}; + \node[state] (q_1) [above=of q_0] {$2$}; + \node[state] (q_2) [right=of $(q_0)!0.5!(q_1)$] {$0$}; + \node[state] (q_3) [right=of q_2] {$3$}; + \path[->] + (q_0) edge node {b} (q_1) + (q_1) edge node[pos=0.3] {a} (q_2) + (q_2) edge node[pos=0.7] {a} (q_0) + (q_2) edge[bend left] node[above] {b} (q_3) + (q_3) edge[bend left] node {b} (q_2); + \end{tikzpicture} +\end{center} + +Его матрица смежности имеет следующий вид. +\[ G_1 = +\begin{pmatrix} +. & \{a\} & . & \{b\} \\ +. & . & \{b\} & . \\ +\{a\} & . & . & . \\ +\{b\} & . & . & . +\end{pmatrix} +\] + +Её булева декомпозиция по каждому символу выглядит следующим образом. +\begin{alignat*}{7} +& &&G_{0\_a} &&= \begin{pmatrix} +0 & 1 & 0 & 0 \\ +0 & 0 & 0 & 0 \\ +1 & 0 & 0 & 0 \\ +0 & 0 & 0 & 0 \\ +\end{pmatrix} \ \ \ \ &&G_{0\_b} &&= \begin{pmatrix} +0 & 0 & 0 & 1 \\ +0 & 0 & 1 & 0 \\ +0 & 0 & 0 & 0 \\ +1 & 0 & 0 & 0 \\ +\end{pmatrix} +\end{alignat*} + +Зададим ограничения с помощью регулярного выражения $b^*ab$, которое представляется автоматом из трех последовательных состояний. + +\begin{center} + \begin{tikzpicture}[shorten >=1pt,on grid,auto] + \node[state, initial] (q_0) at (0,0) {$0$}; + \node[state] (q_1) at (2,0) {$1$}; + \node[state, accepting] (q_2) at (4,0) {$2$}; + \path[->] + (q_0) edge node {$a$} (q_1) + (q_1) edge node {$b$} (q_2); + \draw (q_0) edge[loop above] node {$b$} (q_0); + \end{tikzpicture} +\end{center} + + +Автомат может быть задан матрицей смежности (с дополнительной информацией о стартовых и финальных состояниях). + +Для регулярного выражения $b^*ab$ матрица смежности выглядит следующим образом (при этом нужно запомнить, что +состояние $0$ является начальным, $2$ --- конечным). + +\[ G_2 = +\begin{pmatrix} +\{b\} & \{a\} & . \\ +. & . & \{b\} \\ +. & . & . +\end{pmatrix} +\] + +Нам будет необходима булева декомпозиция этой матрицы, и она выглядит следующим образом. + +\begin{alignat*}{7} + & &&R_{0\_a} &&= \begin{pmatrix} + 0 & 1 & 0 \\ + 0 & 0 & 0 \\ + 0 & 0 & 0 + \end{pmatrix} \ \ \ \ &&R_{0\_b} &&= \begin{pmatrix} + 1 & 0 & 0 \\ + 0 & 0 & 1 \\ + 0 & 0 & 0 + \end{pmatrix} +\end{alignat*} + +Для синхронизации обхода составим набор блочно--диагональных матриц, каждая из которых --- это прямая сумма двух матриц: +$D_{0\_a} = R_{0\_a} \oplus G_{0\_a}$ и $D_{0\_a} = R_{0\_b} \oplus G_{0\_b}$. + +\begin{alignat*}{7} + & &&D_{0\_a} &&= + \left(\begin{array}{c c c | c c c c} + 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + \hline + 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 + \end{array}\right) + \ \ \ \ &&D_{0\_b} &&= + \left(\begin{array}{c c c | c c c c} + 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + \hline + 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 + \end{array}\right) +\end{alignat*} + +Пусть мы решаем частный случай задачи достижимости с несколькими стартовыми вершинами (multiple--source) +--- достижимость с одной стартовой вершиной (single--source). + +Пусть единственной начальной вершиной в графе будет вершина $0$. + +Теперь создадим вектор $v = $ $\fbox{1 0 0} \fbox{1 0 0 0}$, где в первой части стоит единица на месте начального состояния $0$ в автомате. +Во второй части содержится фронт обхода графа, на первом шаге это всегда множество стартовых вершин. В данном случае единица стоит на месте +единственной стартовой вершины --- $0$. + +Совершим один шаг в обходе графа и получим новый фронт обхода графа. +\begin{alignat*}{7} + a:\,\, + & \begin{matrix} + \fbox{1 0 0} \fbox{1 0 0 0} + \end{matrix} && + \times + \left(\begin{array}{c c c | c c c c} + 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + \hline + 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 + \end{array}\right) + &&= \begin{matrix} + \fbox{0 1 0} \fbox{0 1 0 0} + \end{matrix} +\end{alignat*} + +\begin{alignat*}{7} + b:\,\, + & \begin{matrix} + \fbox{1 0 0} \fbox{1 0 0 0} + \end{matrix} && + \times + \left(\begin{array}{c c c | c c c c} + 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + \hline + 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 + \end{array}\right) + &&= \begin{matrix} + \fbox{1 0 0} \fbox{0 0 0 1} + \end{matrix} +\end{alignat*} + +Сложим два полученных вектора, чтобы получить новый фронт обхода графа: $\fbox{0 1 0} \fbox{0 1 0 0}$ + $\fbox{1 0 0} \fbox{0 0 0 1} = \fbox{1 1 0} \fbox{0 1 0 1}$. + +То есть в наш фронт \fbox{0 1 0 1} попали вершины 1 и 3 соотвественно. А именно, мы совершили следующие переходы в графе и автомате. + +\begin{alignat*}{7} + \begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] + \node[state, red] (q_0) {$1$}; + \node[state] (q_1) [above=of q_0] {$2$}; + \node[state] (q_2) [right=of $(q_0)!0.5!(q_1)$] {$0$}; + \node[state, red] (q_3) [right=of q_2] {$3$}; + \path[->, red] + (q_2) edge node[pos=0.7] {a} (q_0) + (q_2) edge[bend left] node[above] {b} (q_3); + \path[->] + (q_0) edge node {b} (q_1) + (q_1) edge node[pos=0.3] {a} (q_2) + (q_3) edge[bend left] node {b} (q_2); + \end{tikzpicture} + &\hspace{20px} + \begin{tikzpicture}[shorten >=1pt,on grid,auto] + \node[state, draw=none] (q_3) at (0,0) {$$}; % empty node for alignment + \node[state, initial, red] (q_0) at (0,1) {$0$}; + \node[state, red] (q_1) at (2,1) {$1$}; + \node[state, accepting] (q_2) at (4,1) {$2$}; + \path[->, red] + (q_0) edge node {$a$} (q_1); + \path[->] + (q_1) edge node {$b$} (q_2); + \draw (q_0) edge[loop above, red] node {$b$} (q_0); + \end{tikzpicture} +\end{alignat*} + +Совершим еще один шаг алгоритма. Теперь вектор $v$, на который мы умножаем матрицы, имеет следующий вид $\fbox{1 1 0} \fbox{0 1 0 1}$. + +\begin{alignat*}{7} + a:\,\, + & \begin{matrix} + \fbox{1 1 0} \fbox{0 1 0 1} + \end{matrix} && + \times + \left(\begin{array}{c c c | c c c c} + 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + \hline + 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 + \end{array}\right) + &&= \begin{matrix} + \fbox{0 1 0} \fbox{0 0 0 0} + \end{matrix} +\end{alignat*} + +\begin{alignat*}{7} + b:\,\, + & \begin{matrix} + \fbox{1 1 0} \fbox{0 1 0 1} + \end{matrix} && + \times + \left(\begin{array}{c c c | c c c c} + 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + \hline + 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 + \end{array}\right) + &&= \begin{matrix} + \fbox{1 0 1} \fbox{1 0 1 0} + \end{matrix} +\end{alignat*} + +$\fbox{0 1 0} \fbox{0 0 0 0}$ + $\fbox{1 0 1} \fbox{1 0 1 0} = \fbox{1 1 1} \fbox{1 0 1 0}$. +То есть в наш фронт \fbox{1 0 1 0} попали вершины 0 и 2 соотвественно. Мы совершили следующие переходы в графе и автомате. + +\begin{alignat*}{7} + \begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] + \node[state, gray] (q_0) {$1$}; + \node[state, teal] (q_1) [above=of q_0] {$2$}; + \node[state, teal] (q_2) [right=of $(q_0)!0.5!(q_1)$] {$0$}; + \node[state, gray] (q_3) [right=of q_2] {$3$}; + \path[->, gray] + (q_2) edge node[pos=0.7] {a} (q_0) + (q_2) edge[bend left] node[above] {b} (q_3); + \path[->, red] + (q_0) edge node {b} (q_1) + (q_3) edge[bend left] node {b} (q_2); + \path[->] + (q_1) edge node[pos=0.3] {a} (q_2); + \end{tikzpicture} + &\hspace{20px} + \begin{tikzpicture}[shorten >=1pt,on grid,auto] + \node[state, draw=none] (q_3) at (0,0) {$$}; % empty node for alignment + \node[state, initial, red] (q_0) at (0,1) {$0$}; + \node[state, gray] (q_1) at (2,1) {$1$}; + \node[state, accepting, teal] (q_2) at (4,1) {$2$}; + \path[->, gray] + (q_0) edge node {$a$} (q_1); + \path[->, red] + (q_1) edge node {$b$} (q_2); + \draw (q_0) edge[loop above, red] node {$b$} (q_0); + \end{tikzpicture} +\end{alignat*} + +При этом, можно заметить, что мы достигли конечной вершины в автомате. Последний элемент левой части результирующего +вектора $\fbox{1 1 \textcolor{red}{1}} \fbox{1 0 1 0}$ отвечает за состояние 2, которое является конечным. А значит, обход необходимо остановить, и текущие вершины фронта +обхода графа записать в ответ. + +Таким образом, вершины графа 0 и 2 являются ответом. Однако вершина 0 --- лишняя. Регулярное выражение $b^*ab$ не подразумевает, что +вершина 0 в графе может быть достигнута. Она могла бы быть достигнута по пустой строке в случае, если бы регулярное выражение имело вид $b^*$ или +по строке $aba$ в случае, если бы регулярное выражение имело вид $b^*aba$. + +Это произошло, потому что в векторе $v$ должна кодироваться информация о паре --- вершине графа и состоянии автомата. +Достигнув вершины 0, мы оказались в конечном состоянии автомата, которое было получено с помощью другой вершины --- вершины 2. + +Эту проблему можно решить, закодировав информацию о каждой такой паре в несколько векторов $v$, и ограничив левую +часть вектора $v$ таким образом, чтобы в ней всегда была лишь одна единица. + +Тогда мы получим, что вектор $v$ вида $\fbox{1 0 0} \fbox{1 0 1 0}$ будет хранить информацию о парах (0, 0) и (0, 2), +где первый элемент пары --- состояние автомата, а второй --- вершина графа. + +Аналогично, вектор $v$ вида $\fbox{0 1 0} \fbox{0 1 1 0}$ кодирует информацию о парах (1, 1) и (1, 2). +Вектор $v$ вида $\fbox{0 0 1} \fbox{0 0 1 1}$ кодирует информацию о парах (2, 2) и (2, 3). + +Таким образом, мы будем понимать, в каком состоянии автомата мы находимся для каждой из вершин фронта обхода графа. + +Рассмотрим, как это применяется в разработанном алгоритме, который представлен далее. + +Предлагается ``расклеить'' $v$ в матрицу $M$, состоящую из трех векторов, добавив два вектора $\fbox{0 1 0} \fbox{0 0 0 0}$ и $\fbox{0 0 1} \fbox{0 0 0 0}$. +Во второй части этих векторов стоят нули, так как \fbox{0 1 0} и \fbox{0 0 1} кодируют состояния автомата 1 и 2, которые не являются начальными. + +\begin{alignat*}{7} + & &&M &&=\begin{matrix} + \fbox{1 0 0} \fbox{1 0 0 0} \\ + \fbox{0 1 0} \fbox{0 0 0 0} \\ + \fbox{0 0 1} \fbox{0 0 0 0} + \end{matrix} +\end{alignat*} + +И совершать обход тем же самым образом, но сохранив с помощью матрицы $M$ дополнительную информацию о парах (состояние, вершина). + +\begin{alignat*}{7} + a:\,\, + & \begin{matrix} + \fbox{1 0 0} \fbox{1 0 0 0} \\ + \fbox{0 1 0} \fbox{0 0 0 0} \\ + \fbox{0 0 1} \fbox{0 0 0 0} + \end{matrix} && + \times + \left(\begin{array}{c c c | c c c c} + 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + \hline + 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 + \end{array}\right) + &&= \begin{matrix} + \fbox{0 1 0} \fbox{0 1 0 0} \\ + \fbox{0 0 0} \fbox{0 0 0 0} \\ + \fbox{0 0 0} \fbox{0 0 0 0} + \end{matrix} +\end{alignat*} + +\begin{alignat*}{7} + b:\,\, + & \begin{matrix} + \fbox{1 0 0} \fbox{1 0 0 0} \\ + \fbox{0 1 0} \fbox{0 0 0 0} \\ + \fbox{0 0 1} \fbox{0 0 0 0} + \end{matrix} && + \times + \left(\begin{array}{c c c | c c c c} + 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + \hline + 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 + \end{array}\right) + &&= \begin{matrix} + \fbox{1 0 0} \fbox{0 0 0 1} \\ + \fbox{0 0 1} \fbox{0 0 0 0} \\ + \fbox{0 0 0} \fbox{0 0 0 0} + \end{matrix} +\end{alignat*} + +Для того, чтобы левая часть матрицы $M$ всегда оставалось единичной, нужно трансформировать в ней строчки особым образом. +Для этого нужно складывать только те вектора в правой части матрицы $M$, у которых в левой части единицы стоят на одинаковых позициях. +После чего переставлять строчки в $M$ так, чтобы левая часть матрицы $M$ принимала единичный вид. +Вектора с пустой левой частью нас при этом не интересуют. + +Тогда правая часть матрицы $M$ будет кодировать текущий фронт обхода графа. + +В нашем примере матрица $M$ для следующего шага обхода выглядит следующим образом. + +\begin{alignat*}{7} + & &&M &&=\begin{matrix} + \fbox{1 0 0} \fbox{0 0 0 1} \\ + \fbox{0 1 0} \fbox{0 1 0 0} \\ + \fbox{0 0 1} \fbox{0 0 0 0} + \end{matrix} +\end{alignat*} + +Видно, что во фронт обхода графа попали вершины 1 и 3. В вершину 1 мы попали в состоянии 1, в вершину 3 --- в состоянии 0. + +Совершаются следующие переходы в графе и автомате. + +\begin{alignat*}{7} + \begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] + \node[state, red] (q_0) {$1$}; + \node[state] (q_1) [above=of q_0] {$2$}; + \node[state] (q_2) [right=of $(q_0)!0.5!(q_1)$] {$0$}; + \node[state, red] (q_3) [right=of q_2] {$3$}; + \path[->, red] + (q_2) edge node[pos=0.7] {a} (q_0) + (q_2) edge[bend left] node[above] {b} (q_3); + \path[->] + (q_0) edge node {b} (q_1) + (q_1) edge node[pos=0.3] {a} (q_2) + (q_3) edge[bend left] node {b} (q_2); + \end{tikzpicture} + &\hspace{20px} + \begin{tikzpicture}[shorten >=1pt,on grid,auto] + \node[state, draw=none] (q_3) at (0,0) {$$}; % empty node for alignment + \node[state, initial, red] (q_0) at (0,1) {$0$}; + \node[state, red] (q_1) at (2,1) {$1$}; + \node[state, accepting] (q_2) at (4,1) {$2$}; + \path[->, red] + (q_0) edge node {$a$} (q_1); + \path[->] + (q_1) edge node {$b$} (q_2); + \draw (q_0) edge[loop above, red] node {$b$} (q_0); + \end{tikzpicture} +\end{alignat*} + +Сделаем еще один шаг алгоритма и придем к конечному состоянию в автомате. + +\begin{alignat*}{7} + a:\,\, + & \begin{matrix} + \fbox{1 0 0} \fbox{0 0 0 1} \\ + \fbox{0 1 0} \fbox{0 1 0 0} \\ + \fbox{0 0 1} \fbox{0 0 0 0} + \end{matrix} && + \times + \left(\begin{array}{c c c | c c c c} + 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + \hline + 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 + \end{array}\right) + &&= \begin{matrix} + \fbox{0 1 0} \fbox{0 0 0 0} \\ + \fbox{0 0 0} \fbox{0 0 0 0} \\ + \fbox{0 0 0} \fbox{0 0 0 0} + \end{matrix} +\end{alignat*} + +\begin{alignat*}{7} + b:\,\, + & \begin{matrix} + \fbox{1 0 0} \fbox{0 0 0 1} \\ + \fbox{0 1 0} \fbox{0 1 0 0} \\ + \fbox{0 0 1} \fbox{0 0 0 0} + \end{matrix} && + \times + \left(\begin{array}{c c c | c c c c} + 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + \hline + 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ + 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ + 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ + 0 & 0 & 0 & 1 & 0 & 0 & 0 + \end{array}\right) + &&= \begin{matrix} + \fbox{1 0 0} \fbox{1 0 0 0} \\ + \fbox{0 0 1} \fbox{0 0 1 0} \\ + \fbox{0 0 0} \fbox{0 0 0 0} + \end{matrix} +\end{alignat*} + +\begin{alignat*}{7} + & &&M &&=\begin{matrix} + \fbox{1 0 0} \fbox{1 0 0 0} \\ + \fbox{0 1 0} \fbox{0 0 0 0} \\ + \fbox{0 0 1} \fbox{0 0 1 0} + \end{matrix} +\end{alignat*} + +Видно, что мы достигли вершины 2 графа в конечном состоянии 2 автомата. При этом вершина 0 графа так же достигнута, как и в наивном варианте алгоритма, но +теперь известно, что это происходит в состоянии 0 автомата. + +\begin{alignat*}{7} + \begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] + \node[state, gray] (q_0) {$1$}; + \node[state, teal] (q_1) [above=of q_0] {$2$}; + \node[state, red] (q_2) [right=of $(q_0)!0.5!(q_1)$] {$0$}; + \node[state, gray] (q_3) [right=of q_2] {$3$}; + \path[->, gray] + (q_2) edge node[pos=0.7] {a} (q_0) + (q_2) edge[bend left] node[above] {b} (q_3); + \path[->, red] + (q_0) edge node {b} (q_1) + (q_3) edge[bend left] node {b} (q_2); + \path[->] + (q_1) edge node[pos=0.3] {a} (q_2); + \end{tikzpicture} + &\hspace{20px} + \begin{tikzpicture}[shorten >=1pt,on grid,auto] + \node[state, draw=none] (q_3) at (0,0) {$$}; % empty node for alignment + \node[state, initial, red] (q_0) at (0,1) {$0$}; + \node[state, gray] (q_1) at (2,1) {$1$}; + \node[state, accepting, teal] (q_2) at (4,1) {$2$}; + \path[->, gray] + (q_0) edge node {$a$} (q_1); + \path[->, red] + (q_1) edge node {$b$} (q_2); + \draw (q_0) edge[loop above, red] node {$b$} (q_0); + \end{tikzpicture} +\end{alignat*} + +Таким образом, в ответ попадает вершина 2. +\end{example} + +Перейдем к формальному описанию алгоритма. + + +Алгоритм принимает на вход граф $\mathcal{G}$, детерминированный конечный автомат $\mathcal{R}$, описывающий регулярную грамматику, и множество начальных вершин $V_{src}$ графа. + +Граф $\mathcal{G}$ и автомат $\mathcal{R}$ можно представить в виде булевых матриц смежности. Так, в виде словаря для каждой метки графа заводится булева матрица смежности, на месте $(i, j)$ ячейки которой стоит 1, если $i$ и $j$ вершины графа соединены ребром данной метки. Такая же операция проводится для автомата грамматики $\mathcal{R}$. + +Далее, мы оперируем с двумя словарями, где ключом является символ метки ребра графа или символ алфавита автомата, а значением --- соответствующая им булевая матрица. + +Для каждого символа из пересечения этих множеств строится матрица $\mathfrak{D}$, как прямая сумма булевых матриц. То есть, строится матрица $\mathfrak{D} = Bool_{\mathcal{R}_a} \bigoplus Bool_{\mathcal{G}_a}$, которая определяется как + +\begin{equation} +\mathfrak{D} = + \left[ + \begin{matrix} + Bool_{\mathcal{R}_a} & 0\\ + 0 & Bool_{\mathcal{G}_a} + \end{matrix} + \right] +\end{equation} + +Где $\mathcal{R}_{a}$ и $\mathcal{G}_{a}$ матрицы смежности соответствующих символов автомата грамматики $\mathcal{R}$ и графа $\mathcal{G}$ для символа $a \in A_\mathcal{R} \cap A_\mathcal{G}$, $A_\mathcal{R} \cap A_\mathcal{G}$ --- пересечение алфавитов. Такая конструкция позволяет синхронизировать алгоритм обхода в ширину одновременно для графа и грамматики. + +Далее вводится матрица $M$, хранящая информацию о фронте обхода графа. Она нужна для выделения множества пройденных вершин и не допускает зацикливание алгоритма. +\begin{equation} +M^{k \times (k + n)} = + \left[ + \begin{matrix} + Id_k & Matrix_{k \times n } + \end{matrix} + \right] +\end{equation} + +Где $Id_k$ --- единичная матрица размера $k$, $k$ --- количество вершин в автомате $\mathcal{R}$, $Matrix_{k \times n }$ --- матрица, хранящая в себе маску пройденных вершин в автомате графа, $n$ --- количество вершин в графе $\mathcal{G}$. + +\subsection{Выходные данные} + +На выходе строится множество $\mathcal{P}$ пар вершин $(v, w)$ графа $\mathcal{G}$ таких, что вершина $w$ достижима из множества начальных вершин, при этом $v \in V_{src}$, $w \not\in V_{src}$. Это множество представляется в виде матрицы размера $|V|\times|V|$, где $(i,j)$ ячейка содержит 1, если пара вершин с индексами $(i, j) \in \mathcal{P}$. + +\subsection{Процесс обхода графа} + +Алгоритм обхода заключается в последовательном умножении матрицы $M$ текущего фронта на матрицу $\mathfrak{D}$. В результате чего, находится матрица $M'$ содержащая информацию о вершинах, достижимых на следующем шаге. Далее, с помощью операций перестановки и сложения векторов $M'$ преобразуется к виду матрицы $M$ и присваивается ей. Итерации продолжаются пока $M'$ содержит новые вершины, не содержащиеся в $M$. На листинге~\ref{BFSRPQ1} представлен этот алгоритм. + +\begin{algorithm}[t] + \caption{Алгоритм достижимости в графе с регулярными ограничениями на основе поиска в ширину, выраженный с помощью операций матричного умножения}\label{BFSRPQ1} + \begin{algorithmic}[1] + \Procedure{BFSBasedRPQ}{$\mathcal{R}=\langle Q, \Sigma, P, F, q \rangle,\mathcal{G}=\langle V, E, L \rangle, V_{src}$} + \State $\mathcal{P}\gets~${Матрица смежности графа} + \State $\mathfrak{D}\gets Bool_\mathcal{R} \bigoplus Bool_\mathcal{G}$\Comment{Построение матриц $\mathfrak{D}$} + \State $M\gets CreateMasks(|Q|,|V|)$ \Comment{Построение матрицы $M$} + \State $M'\gets SetStartVerts(M, V_{src})$ \Comment{Заполнение нач. вершин} + + \While{Матрица~$M$~меняется}{} + \State $M\gets M'\langle\neg M\rangle$\Comment{Применение комплементарной маски} + \ForAll{$a\in (\Sigma \cap L)$} + \State $M'\gets M~$any.pair$~\mathfrak{D}$ + \Comment{Матр. умножение в полукольце} + \State $M'\gets TransformRows(M')$\label{TransformRows} + \Comment{Приведение $M'$ к виду $M$} + \EndFor + \State {$Matrix\gets extractRightSubMatrix(M')$} + \State $V\gets Matrix.reduceVector()$ \Comment{Сложение по столбцам} + \For{$k \in 0\dots|V_{src}|-1$} + \State $W\gets\mathcal{P}.getRow(k)$ + \State $\mathcal{P}.setRow(k, V+W)$ + \EndFor + \EndWhile + \State \textbf{return} $\mathcal{P}$ + \EndProcedure + \end{algorithmic} +\end{algorithm} + +В алгоритме~\ref{BFSRPQ1}, в~\ref{TransformRows} строке происходит трансформация строчек в матрице $M'$. Это делается для того, чтобы представить полученную во время обхода матрицу $M'$, содержащую новый фронт, в виде матрицы $M$. Для этого требуется так переставить строчки $M'$, чтобы она содержала корректные по своему определению значения. То есть, имела единицы на главной диагонали, а все остальные значения в первых $k$ столбцах были нулями. Подробнее эта процедура описана в листинге~\ref{AlgoTransformRows}. + +\begin{algorithm}[H] + \caption{Алгоритм трансформации строчек}\label{AlgoTransformRows} + \begin{algorithmic}[1] + \Procedure{TransformRows}{$M$} + \State{$T \gets extractLeftSubMatrix(M)$} + \State{$Ix, Iy \gets$ итераторы по индексам ненулевых элементов $T$} + \For{$i \in 0\dots|Iy|$} + \State{$R\gets M.getRow(Ix[i])$} + \State{$M'.setRow(Iy[i], R + M'.getRow(Iy[i]))$} + \EndFor + \EndProcedure + \end{algorithmic} +\end{algorithm} + +\pagebreak + +\subsection{Модификации алгоритма} + +Рассмотрим $V_{src}$ --- множество начальных вершин, состоящее из $r$ элементов. Для каждой начальной вершины $v_{src}^i \in V_{src}$ отметим соответствующие индексы в матрице $M$ единицами, получив матрицу $M(v_{src}^i)$, и построим матрицу $\mathfrak{M}$ следующим образом. + +\begin{equation} +\mathfrak{M}^{(k*r) \times (k + n)} = + \left[ + \begin{matrix} + M(v_{src}^1) \\ + M(v_{src}^2) \\ + M(\dots) \\ + M(v_{src}^r) \\ + \end{matrix} + \right] +\end{equation} + +Матрица $\mathfrak{M}$ собирается из множества матриц $M(v_{src}^i)$ и позволяет хранить информацию о том, из какой начальной вершины достигаются новые вершины во время обхода. + +\begin{algorithm}[t] + \caption{Модификация алгоритма для поиска конкретной исходной вершины}\label{BFSRPQ2} + \begin{algorithmic}[1] + \Procedure{BFSBasedRPQ}{$\mathcal{R}=\langle Q, \Sigma, P, F, q \rangle,\mathcal{G}=\langle V, E, L \rangle, V_{src}$} + \State $\mathcal{P}\gets~${Матрица смежности графа} + \State $\mathfrak{D}\gets Bool_\mathcal{R} \bigoplus Bool_\mathcal{G}$ + \State $\mathfrak{M}\gets CreateMasks(|Q|,|V|)$ + \State $\mathfrak{M}'\gets SetStartVerts(\mathfrak{M}, V_{src})$ + + \While{Матрица~$\mathfrak{M}$~меняется}{} + \State $\mathfrak{M}\gets \mathfrak{M}'\langle\neg\mathfrak{M}\rangle$ + \ForAll{$a\in (\Sigma \cap L)$} + \State $\mathfrak{M}'\gets \mathfrak{M}~$any.pair$~\mathfrak{D}$ + \ForAll{$M \in \mathfrak{M}'$} + \State $M\gets TransformRows(M)$ + \EndFor + \EndFor + \ForAll{$M_k \in \mathfrak{M}'$} + \State $Matrix\gets extractSubMatrix(M)$ + \State $V\gets Matrix.reduceVector()$ + \State $W\gets\mathcal{P}.getRow(k)$ + \State $\mathcal{P}.setRow(k, V+W)$ + \EndFor + \EndWhile + \State \textbf{return} $\mathcal{P}$ + \EndProcedure + \end{algorithmic} +\end{algorithm} + +В листинге~\ref{BFSRPQ2} представлен модифицированный алгоритм. Основное его отличие заключается в том, что для каждой достижимой вершины находится конкретная исходная вершина, из которой начинался обход. + +Таким образом, алгоритмы~\ref{BFSRPQ1}~и~\ref{BFSRPQ2} решают сформулированные в пункте \ref{sec:3.3} задачи достижимости. \ No newline at end of file diff --git a/tex/SPPF.tex b/tex/SPPF.tex new file mode 100644 index 0000000..0f02999 --- /dev/null +++ b/tex/SPPF.tex @@ -0,0 +1,717 @@ +\chapter{Сжатое представление леса разбора} + +Матричный алгоритм даёт нам ответ на вопрос о достижимости, но не предоставляет самих путей. +Что делать, если мы хотим построить все пути, удовлетворяющие ограничениям? + +Проблема в том, что искомое множество путей может быть бесконечным. +Можем ли мы предложить конечную структуру, однозначно описывающую такое множество? +Вспомним, что пересечение контекстно-свободного языка с регулярным --- это контекстно-свободный язык. +Мы знаем, что контекстно-свободный язык можно описать контекстно-свободной грамматикой, которая конечна. +Это и есть решение нашего вопроса. +Осталось только научиться строить такую грамматику. + +Прежде, чем двинуться дальше, рекомендуется вспомнить всё, что касается деревьев вывода~\ref{sect:DerivTree}. + +\section[Лес разбора как представление контекстно-свободной грамматики]{Лес разбора как представление контекстно-свободной грамматики\sectionmark{Лес разбора как представление КС грамматики}} +\sectionmark{Лес разбора как представление КС грамматики} + +Для начала нам потребуется внести некоторые изменения в конструкцию дерева вывода. + +Во-первых, заметим, что в дереве вывода каждый узел соответствует выводу какой-то подстроки с известными позициями начала и конца. +Давайте будем сохранять эту информацию в узлах дерева. +Таким образом, метка любого узла это тройка вида $(i,q,j)$, где $i$ --- координата начала подстроки, соответствующей этому узлу, $j$ --- координата конца, $q \in \Sigma \cup N$ --- метка как в исходном определении. + +Во-вторых, заметим, что внутренний узел со своими сыновьями связаны с продукцией в грамматике: узел появляется благодаря применению конкретной продукции в процессе вывода. +Давайте занумеруем все продукции в грамматике и добавим в дерево вывода ещё один тип узлов (дополнительные узлы), в которых будем хранить номер применённой продукции. +Получим следующую конструкцию: непосредственный предок дополнительного узла --- это левая часть продукции, а непосредственные сыновья дополнительного узла --- это правая часть продукции. + +\begin{example} + Построим модифицированное дерево вывода цепочки $_0a_1b_2a_3b_4a_5b_6$ в грамматике + + \begin{align*} + G_0 = \langle \{a,b\}, \{S\}, S, \{ & \\ + & \ \ (0) S \to a \ S \ b \ S, \\ + & \ \ (1) S \to \varepsilon \\ + & \} \rangle + \end{align*} + + + +\begin{center} +\resizebox{0.9\textwidth}{!}{ +\begin{tikzpicture}[shorten >=1pt,node distance=1.2cm] + \node[symbol_node] (s_0_6) {$(0,S,6)$}; + \node[prod_node] (p_0_1) [below=of s_0_6] {$0$}; + \node[prod_node,draw=none] (dummy1) [below =of p_0_1] {}; + \node[symbol_node] (s_1_1) [below left=of p_0_1] {$(1,S,1)$}; + \node[symbol_node] (s_2_6) [below right=of p_0_1] {$(2,S,6)$}; + + \node[prod_node] (p_0_2) [below right=of s_2_6] {$0$}; + + \node[symbol_node] (s_3_3) [below left=of p_0_2] {$(3,S,3)$}; + \node[symbol_node] (s_4_6) [below right=of p_0_2] {$(4,S,6)$}; + + \node[prod_node] (p_0_3) [below right =of s_4_6] {0}; + + \node[symbol_node] (s_5_5) [below =of p_0_3] {$(5,S,5)$}; + \node[symbol_node] (s_6_6) [below right=of p_0_3] {$(6,S,6)$}; + +% \node[state,draw=none] (dummy1) [below =of s_0_6] {}; +% \node[state,draw=none] (dummy2) [below =of dummy1] {}; + +% \node[state,draw=none] (dummy3) [below left=of p_0_3] {}; +% \node[state,draw=none] (dummy4) [below right=of p_0_4] {}; + + +% \node[symbol_node] (s_0_2) [left=of dummy3] {$(0,S,2)$}; +% +% \node[symbol_node] (s_2_4) [between=s_0_2 and s_4_6] {$(2,S,4)$}; + + + \node[prod_node] (p_1_1) [below left =of s_1_1] {$1$}; + \node[prod_node] (p_1_2) [below left =of s_3_3] {$1$}; + \node[prod_node] (p_1_3) [below =of s_5_5] {$1$}; + \node[prod_node] (p_1_4) [below right=of s_6_6] {$1$}; + + + +% \node[prod_node] (p_2_1) [below =of s_1_1] {$2$}; +% \node[prod_node] (p_2_2) [below =of s_3_3] {$2$}; +% \node[prod_node] (p_2_3) [below =of s_5_5] {$2$}; + + \node[symbol_node] (eps_6_6) [below right=of p_1_4] {$(6,\varepsilon,6)$}; + \node[symbol_node] (b_5_6) [left=of eps_6_6] {$(5,b,6)$}; + \node[symbol_node] (eps_5_5) [left =of b_5_6] {$(5,\varepsilon,5)$}; + \node[symbol_node] (a_4_5) [left=of eps_5_5] {$(4,a,5)$}; + \node[symbol_node] (b_3_4) [left=of a_4_5] {$(3,b,4)$}; + \node[symbol_node] (eps_3_3) [left =of b_3_4] {$(3,\varepsilon,3)$}; + \node[symbol_node] (a_2_3) [left=of eps_3_3] {$(2,a,3)$}; + \node[symbol_node] (b_1_2) [left=of a_2_3] {$(1,b,2)$}; + \node[symbol_node] (eps_1_1) [left =of b_1_2] {$(1,\varepsilon,1)$}; + \node[symbol_node] (a_0_1) [left=of eps_1_1] {$(0,a,1)$}; + + + \path[->] + (s_0_6) edge (p_0_1) + + (p_0_1) edge [bend right] (a_0_1) + (p_0_1) edge (s_1_1) + (p_0_1) edge (b_1_2) + (p_0_1) edge (s_2_6) + + (s_2_6) edge (p_0_2) + + (p_0_2) edge [bend right] (a_2_3) + (p_0_2) edge (s_3_3) + (p_0_2) edge (b_3_4) + (p_0_2) edge (s_4_6) + + (s_4_6) edge (p_0_3) + + (p_0_3) edge (a_4_5) + (p_0_3) edge (s_5_5) + (p_0_3) edge (b_5_6) + (p_0_3) edge (s_6_6) + + (s_1_1) edge (p_1_1) + (p_1_1) edge (eps_1_1) + + (s_3_3) edge (p_1_2) + (p_1_2) edge (eps_3_3) + + (s_5_5) edge (p_1_3) + (p_1_3) edge (eps_5_5) + + (s_6_6) edge (p_1_4) + (p_1_4) edge (eps_6_6) + + + ; +\end{tikzpicture} +} +\end{center} + + +\end{example} + + +Сохраняемая нами дополнительная информация позволит переиспользовать узлы в том случае, если деревьев вывода оказалось несколько (в случае неоднозначной грамматики). +При этом мы можем не бояться, что переиспользование узлов может привести к появлению ранее несуществовавших деревьев вывода, так как дополнительная информация позволяет делать только ``безопасные'' склейки и затем восстанавливать только корректные деревья. Таким образом, мы можем представить лес вывода в виде единой структуры данных без дублирования информации. + + +\begin{example} + Сжатие леса вывода. + Построим несколько деревьев вывода цепочки $_0a_1b_2a_3b_4a_5b_6$ в грамматике + + \begin{align*} + G_1 = \langle \{a,b\}, \{S\}, S, \{ & \\ + & \ \ (0) S \to S S, \\ + & \ \ (1) S \to a \ S \ b, \\ + & \ \ (2) S \to \varepsilon \\ + & \} \rangle + \end{align*} + +Предположим, что мы строим левосторонний вывод. +Тогда после первого применения продукции 0 у нас есть два варианта переписывания первого нетерминала: либо с применением продукции 0, либо с применением продукции 1: +\begin{align*} +&\textbf{S} \xrightarrow{0} \textbf{S}S \xrightarrow{0} \textbf{S}SS \xrightarrow{1} a\textbf{S}bSS \xrightarrow{2} ab\textbf{S}S \xrightarrow{1} aba\textbf{S}bS \xrightarrow{2} abab\textbf{S} \xrightarrow{1} ababa\textbf{S}b \xrightarrow{2} ababab +\\ +&\textbf{S} \xrightarrow{0} \textbf{S}S \xrightarrow{1} a\textbf{S}bS \xrightarrow{2} ab\textbf{S} \xrightarrow{0} ab\textbf{S}S \xrightarrow{1} aba\textbf{S}bS \xrightarrow{2} abab\textbf{S} \xrightarrow{1} ababa\textbf{S}b \xrightarrow{2} ababab +\end{align*} + +Сначала рассмотрим первый вариант (применили переписывание по продукции 0). +Все остальные шаги вывода деретерминированы и в результате мы получим следующее дерево разбора: + +\begin{center} +\resizebox{0.9\textwidth}{!}{ +\begin{tikzpicture}[shorten >=1pt,on grid,auto,node distance=1.8cm] + \node[symbol_node] (s_0_6) {$(0,S,6)$}; + \node[prod_node] (p_0_1) [below left=of s_0_6] {$0$}; + \node[prod_node,draw=none] (p_0_2) [below right=of s_0_6] {}; + \node[symbol_node] (s_0_4) [below left=of p_0_1] {$(0,S,4)$}; + \node[symbol_node,draw=none] (s_2_6) [below right=of p_0_2] {}; + \node[prod_node] (p_0_3) [below =of s_0_4] {$0$}; + \node[prod_node,draw=none] (p_0_4) [below =of s_2_6] {}; + + \node[state,draw=none] (dummy1) [below =of s_0_6] {}; + \node[state,draw=none] (dummy2) [below =of dummy1] {}; + + \node[state,draw=none] (dummy3) [below left=of p_0_3] {}; + \node[state,draw=none] (dummy4) [below right=of p_0_4] {}; + + + \node[symbol_node] (s_0_2) [left=of dummy3] {$(0,S,2)$}; + \node[symbol_node] (s_4_6) [right=of dummy4] {$(4,S,6)$}; + \node[symbol_node] (s_2_4) [between=s_0_2 and s_4_6] {$(2,S,4)$}; + + \node[prod_node] (p_1_1) [below =of s_0_2] {$1$}; + \node[prod_node] (p_1_2) [below =of s_2_4] {$1$}; + \node[prod_node] (p_1_3) [below =of s_4_6] {$1$}; + + \node[symbol_node] (s_1_1) [below =of p_1_1] {$(1,S,1)$}; + \node[symbol_node] (s_3_3) [below =of p_1_2] {$(3,S,3)$}; + \node[symbol_node] (s_5_5) [below =of p_1_3] {$(5,S,5)$}; + + \node[prod_node] (p_2_1) [below =of s_1_1] {$2$}; + \node[prod_node] (p_2_2) [below =of s_3_3] {$2$}; + \node[prod_node] (p_2_3) [below =of s_5_5] {$2$}; + + \node[symbol_node] (eps_1_1) [below =of p_2_1] {$(1,\varepsilon,1)$}; + \node[symbol_node] (eps_3_3) [below =of p_2_2] {$(3,\varepsilon,3)$}; + \node[symbol_node] (eps_5_5) [below =of p_2_3] {$(5,\varepsilon,5)$}; + + \node[symbol_node] (a_0_1) [left=of eps_1_1] {$(0,a,1)$}; + \node[symbol_node] (a_2_3) [left=of eps_3_3] {$(2,a,3)$}; + \node[symbol_node] (a_4_5) [left=of eps_5_5] {$(4,a,5)$}; + + \node[symbol_node] (b_1_2) [right=of eps_1_1] {$(1,b,2)$}; + \node[symbol_node] (b_3_4) [right=of eps_3_3] {$(3,b,4)$}; + \node[symbol_node] (b_5_6) [right=of eps_5_5] {$(5,b,6)$}; + + + \path[->] + (s_0_6) edge (p_0_1) +% (s_0_6) edge (p_0_2) + (p_0_1) edge (s_0_4) + (p_0_1) edge (s_4_6) +% (p_0_2) edge (s_0_2) +% (p_0_2) edge (s_2_6) + (s_0_4) edge (p_0_3) +% (s_2_6) edge (p_0_4) + (p_0_3) edge (s_0_2) + (p_0_3) edge (s_2_4) +% (p_0_4) edge (s_2_4) +% (p_0_4) edge (s_4_6) + + (s_0_2) edge (p_1_1) + (s_2_4) edge (p_1_2) + (s_4_6) edge (p_1_3) + + (p_1_1) edge [bend right] (a_0_1) + (p_1_1) edge (s_1_1) + (p_1_1) edge [bend left] (b_1_2) + + (p_1_2) edge [bend right] (a_2_3) + (p_1_2) edge (s_3_3) + (p_1_2) edge [bend left] (b_3_4) + + (p_1_3) edge [bend right] (a_4_5) + (p_1_3) edge (s_5_5) + (p_1_3) edge [bend left] (b_5_6) + + (s_1_1) edge (p_2_1) + (p_2_1) edge (eps_1_1) + + (s_3_3) edge (p_2_2) + (p_2_2) edge (eps_3_3) + + (s_5_5) edge (p_2_3) + (p_2_3) edge (eps_5_5) + + ; +\end{tikzpicture} +} +\end{center} + +Теперь рассмотрим второй вариант --- применить продукцию 1. +Остальные шаги вывода всё также детерминированы. +В результате мы получим следующее дерево вывода: + +\begin{center} +\resizebox{0.9\textwidth}{!}{ +\begin{tikzpicture}[shorten >=1pt,on grid,auto,node distance=1.8cm] + \node[symbol_node] (s_0_6) {$(0,S,6)$}; + \node[prod_node,draw=none] (p_0_1) [below left=of s_0_6] {}; + \node[prod_node] (p_0_2) [below right=of s_0_6] {$0$}; + \node[symbol_node,draw=none] (s_0_4) [below left=of p_0_1] {}; + \node[symbol_node] (s_2_6) [below right=of p_0_2] {$(2,S,6)$}; + \node[prod_node,draw=none] (p_0_3) [below =of s_0_4] {}; + \node[prod_node] (p_0_4) [below =of s_2_6] {$0$}; + + \node[state,draw=none] (dummy1) [below =of s_0_6] {}; + \node[state,draw=none] (dummy2) [below =of dummy1] {}; + + \node[state,draw=none] (dummy3) [below left=of p_0_3] {}; + \node[state,draw=none] (dummy4) [below right=of p_0_4] {}; + + + \node[symbol_node] (s_0_2) [left=of dummy3] {$(0,S,2)$}; + \node[symbol_node] (s_4_6) [right=of dummy4] {$(4,S,6)$}; + \node[symbol_node] (s_2_4) [between=s_0_2 and s_4_6] {$(2,S,4)$}; + + \node[prod_node] (p_1_1) [below =of s_0_2] {$1$}; + \node[prod_node] (p_1_2) [below =of s_2_4] {$1$}; + \node[prod_node] (p_1_3) [below =of s_4_6] {$1$}; + + \node[symbol_node] (s_1_1) [below =of p_1_1] {$(1,S,1)$}; + \node[symbol_node] (s_3_3) [below =of p_1_2] {$(3,S,3)$}; + \node[symbol_node] (s_5_5) [below =of p_1_3] {$(5,S,5)$}; + + \node[prod_node] (p_2_1) [below =of s_1_1] {$2$}; + \node[prod_node] (p_2_2) [below =of s_3_3] {$2$}; + \node[prod_node] (p_2_3) [below =of s_5_5] {$2$}; + + \node[symbol_node] (eps_1_1) [below =of p_2_1] {$(1,\varepsilon,1)$}; + \node[symbol_node] (eps_3_3) [below =of p_2_2] {$(3,\varepsilon,3)$}; + \node[symbol_node] (eps_5_5) [below =of p_2_3] {$(5,\varepsilon,5)$}; + + \node[symbol_node] (a_0_1) [left=of eps_1_1] {$(0,a,1)$}; + \node[symbol_node] (a_2_3) [left=of eps_3_3] {$(2,a,3)$}; + \node[symbol_node] (a_4_5) [left=of eps_5_5] {$(4,a,5)$}; + + \node[symbol_node] (b_1_2) [right=of eps_1_1] {$(1,b,2)$}; + \node[symbol_node] (b_3_4) [right=of eps_3_3] {$(3,b,4)$}; + \node[symbol_node] (b_5_6) [right=of eps_5_5] {$(5,b,6)$}; + + + \path[->] + %(s_0_6) edge (p_0_1) + (s_0_6) edge (p_0_2) + %(p_0_1) edge (s_0_4) + %(p_0_1) edge (s_4_6) + (p_0_2) edge (s_0_2) + (p_0_2) edge (s_2_6) + %(s_0_4) edge (p_0_3) + (s_2_6) edge (p_0_4) + %(p_0_3) edge (s_0_2) + %(p_0_3) edge (s_2_4) + (p_0_4) edge (s_2_4) + (p_0_4) edge (s_4_6) + + (s_0_2) edge (p_1_1) + (s_2_4) edge (p_1_2) + (s_4_6) edge (p_1_3) + + (p_1_1) edge [bend right] (a_0_1) + (p_1_1) edge (s_1_1) + (p_1_1) edge [bend left] (b_1_2) + + (p_1_2) edge [bend right] (a_2_3) + (p_1_2) edge (s_3_3) + (p_1_2) edge [bend left] (b_3_4) + + (p_1_3) edge [bend right] (a_4_5) + (p_1_3) edge (s_5_5) + (p_1_3) edge [bend left] (b_5_6) + + (s_1_1) edge (p_2_1) + (p_2_1) edge (eps_1_1) + + (s_3_3) edge (p_2_2) + (p_2_2) edge (eps_3_3) + + (s_5_5) edge (p_2_3) + (p_2_3) edge (eps_5_5) + + ; +\end{tikzpicture} +} +\end{center} + +В двух построенных деревьях большое количество одинаковых узлов. +Построим структуру, которая содержит оба дерева и при этом никакие нетерминальные и терминальные узлы не встречаются дважды. +В результате мы получим следующий граф: + +\begin{center} +\resizebox{0.9\textwidth}{!}{ +\begin{tikzpicture}[shorten >=1pt,on grid,auto,node distance=1.8cm] + \node[symbol_node] (s_0_6) {$(0,S,6)$}; + \node[prod_node] (p_0_1) [below left=of s_0_6] {$0$}; + \node[prod_node] (p_0_2) [below right=of s_0_6] {$0$}; + \node[symbol_node] (s_0_4) [below left=of p_0_1] {$(0,S,4)$}; + \node[symbol_node] (s_2_6) [below right=of p_0_2] {$(2,S,6)$}; + \node[prod_node] (p_0_3) [below =of s_0_4] {$0$}; + \node[prod_node] (p_0_4) [below =of s_2_6] {$0$}; + + \node[state,draw=none] (dummy1) [below =of s_0_6] {}; + \node[state,draw=none] (dummy2) [below =of dummy1] {}; + + \node[state,draw=none] (dummy3) [below left=of p_0_3] {}; + \node[state,draw=none] (dummy4) [below right=of p_0_4] {}; + + + \node[symbol_node] (s_0_2) [left=of dummy3] {$(0,S,2)$}; + \node[symbol_node] (s_4_6) [right=of dummy4] {$(4,S,6)$}; + \node[symbol_node] (s_2_4) [between=s_0_2 and s_4_6] {$(2,S,4)$}; + + \node[prod_node] (p_1_1) [below =of s_0_2] {$1$}; + \node[prod_node] (p_1_2) [below =of s_2_4] {$1$}; + \node[prod_node] (p_1_3) [below =of s_4_6] {$1$}; + + \node[symbol_node] (s_1_1) [below =of p_1_1] {$(1,S,1)$}; + \node[symbol_node] (s_3_3) [below =of p_1_2] {$(3,S,3)$}; + \node[symbol_node] (s_5_5) [below =of p_1_3] {$(5,S,5)$}; + + \node[prod_node] (p_2_1) [below =of s_1_1] {$2$}; + \node[prod_node] (p_2_2) [below =of s_3_3] {$2$}; + \node[prod_node] (p_2_3) [below =of s_5_5] {$2$}; + + \node[symbol_node] (eps_1_1) [below =of p_2_1] {$(1,\varepsilon,1)$}; + \node[symbol_node] (eps_3_3) [below =of p_2_2] {$(3,\varepsilon,3)$}; + \node[symbol_node] (eps_5_5) [below =of p_2_3] {$(5,\varepsilon,5)$}; + + \node[symbol_node] (a_0_1) [left=of eps_1_1] {$(0,a,1)$}; + \node[symbol_node] (a_2_3) [left=of eps_3_3] {$(2,a,3)$}; + \node[symbol_node] (a_4_5) [left=of eps_5_5] {$(4,a,5)$}; + + \node[symbol_node] (b_1_2) [right=of eps_1_1] {$(1,b,2)$}; + \node[symbol_node] (b_3_4) [right=of eps_3_3] {$(3,b,4)$}; + \node[symbol_node] (b_5_6) [right=of eps_5_5] {$(5,b,6)$}; + + + \path[->] + (s_0_6) edge (p_0_1) + (s_0_6) edge (p_0_2) + (p_0_1) edge (s_0_4) + (p_0_1) edge (s_4_6) + (p_0_2) edge (s_0_2) + (p_0_2) edge (s_2_6) + (s_0_4) edge (p_0_3) + (s_2_6) edge (p_0_4) + (p_0_3) edge (s_0_2) + (p_0_3) edge (s_2_4) + (p_0_4) edge (s_2_4) + (p_0_4) edge (s_4_6) + + (s_0_2) edge (p_1_1) + (s_2_4) edge (p_1_2) + (s_4_6) edge (p_1_3) + + (p_1_1) edge [bend right] (a_0_1) + (p_1_1) edge (s_1_1) + (p_1_1) edge [bend left] (b_1_2) + + (p_1_2) edge [bend right] (a_2_3) + (p_1_2) edge (s_3_3) + (p_1_2) edge [bend left] (b_3_4) + + (p_1_3) edge [bend right] (a_4_5) + (p_1_3) edge (s_5_5) + (p_1_3) edge [bend left] (b_5_6) + + (s_1_1) edge (p_2_1) + (p_2_1) edge (eps_1_1) + + (s_3_3) edge (p_2_2) + (p_2_2) edge (eps_3_3) + + (s_5_5) edge (p_2_3) + (p_2_3) edge (eps_5_5) + + ; +\end{tikzpicture} +} +\end{center} + + +\end{example} + + +Мы получили очень простой вариант сжатого представления леса разбора (Shared Packed Parse Forest, SPPF). +Впервые подобная идея была предложена Джоаном Рекерсом в его кандидатской диссертации~\cite{SPPF}. +В дальнейшем она нашла широкое применение в обобщённом (generalized) синтаксическом анализе и получила серьёзное развитие. +В частности, наш вариант, хоть и позволяет избежать экспоненциального разрастания леса разбора, всё же не является оптимальным. +Оптимальное асимптотическое поведение достигается при использовании бинаризованного SPPF~\cite{Billot:1989:SSF:981623.981641} --- в этом случае объём леса составляет $O(n^3)$, где $n$ --- это длина входной строки. + +Различные модификации SPPF применяются в таких алгоритмах синтаксического анализа, как RNGLR~\cite{Scott:2006:RNG:1146809.1146810}, бинаризованная верся SPPF в BRNGLR~\cite{Scott:2007:BCT:1289813.1289815} и GLL~\cite{Scott:2010:GP:1860132.1860320,10.1007/978-3-662-46663-6_5}\footnote{Ещё немного полезной информации про SPPF: \url{http://www.bramvandersanden.com/post/2014/06/shared-packed-parse-forest/}.}. + +В действительности SPPF может содержать в себе циклы. Для линейного входа их можно получить, когда есть возможность выводить по грамматике бесконечные эпсилон-цепочки. Циклы будут вырожденными, но они будут. + +Мы, кроме традиционного использования, будем применять SPPF для представления результатов КС запросов к графам. + +В графе может существовать множество способов получить путь из одной вершины в другую. И точно так же при построении деревьев вывода путей может появиться несколько одинаковых нетерминалов, получаемых в разных деревьях по-разному. При объединении в SPPF может оказаться, что какой-то путь из вершины $a$ в вершину $b$ является подпутем другого пути из вершины $a$ в вершину $b$, просто более длинного. То есть появятся циклические зависимости. + +\begin{example} + Рассмотрим пример SPPF для задачи поиска путей с КС ограничениями. + Пусть дан граф $\mathcal{G}:$ + + \begin{center} + \input{figures/graph/graph0.tex} + \end{center} + + Дана грамматика + + \begin{align*} + G = \langle \{a,b\}, \{S\}, S, \ & \{ \\ + & \ \ (0)\ S \to a \ S \ b, \\ + & \ \ (1)\ S \to a \ b, \\ + \ & \} \rangle + \end{align*} + + + Попробуем найти все пути из вершины 2 в вершину 2, выводимые из нетерминала $S$. + Проверить наличие такого пути можно используя уже известные нам алгоритмы, однако сами пути пока будем строить ``методом пристального взгляда''. Найдем один из них. Пусть это будет + $$2 \xrightarrow{a} 0 \xrightarrow{a} 1 \xrightarrow{a} 2 \xrightarrow{a} 0 \xrightarrow{a} 1 \xrightarrow{a} 2 \xrightarrow{b} 3 \xrightarrow{b} 2 \xrightarrow{b} 3 \xrightarrow{b} 2 \xrightarrow{b} 3 \xrightarrow{b} 2. + $$ + Построим дерево его вывода. + + \begin{center} + \resizebox{0.3\textwidth}{!}{ + \begin{tikzpicture}[shorten >=1pt,on grid,auto,node distance=1.8cm] + \node[symbol_node] (s_2_2) {$(2,S,2)$}; + + \node[prod_node] (p_0_1) [below =of s_0_6] {$0$}; + \node[symbol_node] (s_0_3) [below =of p_0_1] {$(0,S,3)$}; + \node[symbol_node] (a_2_0_1) [left =of s_0_3] {$(2,a,0)$}; + \node[symbol_node] (b_3_2_1) [right=of s_0_3] {$(3,b,2)$}; + + \node[prod_node] (p_0_2) [below =of s_0_3] {$0$}; + \node[symbol_node] (s_1_2) [below =of p_0_2] {$(1,S,2)$}; + \node[symbol_node] (a_0_1_1) [left =of s_1_2] {$(0,a,1)$}; + \node[symbol_node] (b_2_3_1) [right=of s_1_2] {$(2,b,3)$}; + + \node[prod_node] (p_0_3) [below =of s_1_2] {$0$}; + \node[symbol_node] (s_2_3) [below =of p_0_3] {$(2,S,3)$}; + \node[symbol_node] (a_1_2_1) [left =of s_2_3] {$(1,a,2)$}; + \node[symbol_node] (b_3_2_2) [right=of s_2_3] {$(3,b,2)$}; + + \node[prod_node] (p_0_4) [below =of s_2_3] {$0$}; + \node[symbol_node] (s_0_2) [below =of p_0_4] {$(0,S,2)$}; + \node[symbol_node] (a_2_0_2) [left =of s_0_2] {$(2,a,0)$}; + \node[symbol_node] (b_2_3_2) [right=of s_0_2] {$(2,b,3)$}; + + \node[prod_node] (p_0_5) [below =of s_0_2] {$0$}; + \node[symbol_node] (s_1_3) [below =of p_0_5] {$(1,S,3)$}; + \node[symbol_node] (a_0_1_2) [left =of s_1_3] {$(0,a,1)$}; + \node[symbol_node] (b_3_2_3) [right=of s_1_3] {$(3,b,2)$}; + + \node[prod_node] (p_1_1) [below =of s_1_3] {$1$}; + \node[symbol_node] (a_1_2_2) [below left =of p_1_1] {$(1,a,2)$}; + \node[symbol_node] (b_2_3_3) [below right=of p_1_1] {$(2,b,3)$}; + + \path[->] + (s_2_2) edge (p_0_1) + + (p_0_1) edge (s_0_3) + (p_0_1) edge (a_2_0_1) + (p_0_1) edge (b_3_2_1) + + (s_0_3) edge (p_0_2) + + (p_0_2) edge (s_1_2) + (p_0_2) edge (a_0_1_1) + (p_0_2) edge (b_2_3_1) + + (s_1_2) edge (p_0_3) + + (p_0_3) edge (s_2_3) + (p_0_3) edge (a_1_2_1) + (p_0_3) edge (b_3_2_2) + + (s_2_3) edge (p_0_4) + + (p_0_4) edge (s_0_2) + (p_0_4) edge (a_2_0_2) + (p_0_4) edge (b_2_3_2) + + (s_0_2) edge (p_0_5) + + (p_0_5) edge (s_1_3) + (p_0_5) edge (a_0_1_2) + (p_0_5) edge (b_3_2_3) + + (s_1_3) edge (p_1_1) + + (p_1_1) edge (a_1_2_2) + (p_1_1) edge (b_2_3_3) + + ; + \end{tikzpicture} + } + \end{center} + + Мы построили дерево вывода для одного пути из вершины 2 в неё же. + Но можно заметить, что таких путей бесконечно много: мы можем бесконечное число раз повторять уже выполненный обход и получать всё более длинные пути. + В терминах дерева вывода это будет означать, что к узлу $_1S_3$ мы добавим сына, соответствующего применению продукции 0, а не 1 для нетерминала $S$. + В таком случае мы получим узел $_2S_2$, который уже существует в дереве и таким образом замкнём цикл. + + \begin{center} + \resizebox{0.5\textwidth}{!}{ + \begin{tikzpicture}[shorten >=1pt,on grid,auto,node distance=1.8cm] + \node[symbol_node] (s_2_2) {$(2,S,2)$}; + + \node[prod_node] (p_0_1) [below =of s_0_6] {$0$}; + \node[symbol_node] (s_0_3) [below =of p_0_1] {$(0,S,3)$}; + \node[symbol_node] (a_2_0_1) [left =of s_0_3] {$(2,a,0)$}; + \node[symbol_node] (b_3_2_1) [right=of s_0_3] {$(3,b,2)$}; + + \node[prod_node] (p_0_2) [below =of s_0_3] {$0$}; + \node[symbol_node] (s_1_2) [below =of p_0_2] {$(1,S,2)$}; + \node[symbol_node] (a_0_1_1) [left =of s_1_2] {$(0,a,1)$}; + \node[symbol_node] (b_2_3_1) [right=of s_1_2] {$(2,b,3)$}; + + \node[prod_node] (p_0_3) [below =of s_1_2] {$0$}; + \node[symbol_node] (s_2_3) [below =of p_0_3] {$(2,S,3)$}; + \node[symbol_node] (a_1_2_1) [left =of s_2_3] {$(1,a,2)$}; + \node[symbol_node] (b_3_2_2) [right=of s_2_3] {$(3,b,2)$}; + + \node[prod_node] (p_0_4) [below =of s_2_3] {$0$}; + \node[symbol_node] (s_0_2) [below =of p_0_4] {$(0,S,2)$}; + \node[symbol_node] (a_2_0_2) [left =of s_0_2] {$(2,a,0)$}; + \node[symbol_node] (b_2_3_2) [right=of s_0_2] {$(2,b,3)$}; + + \node[prod_node] (p_0_5) [below =of s_0_2] {$0$}; + \node[symbol_node] (s_1_3) [below =of p_0_5] {$(1,S,3)$}; + \node[symbol_node] (a_0_1_2) [left =of s_1_3] {$(0,a,1)$}; + \node[symbol_node] (b_3_2_3) [right=of s_1_3] {$(3,b,2)$}; + + \node[state,draw=none] (dummy1) [below left=of s_1_3] {}; + \node[state,draw=none] (dummy2) [below right=of s_1_3] {}; + \node[prod_node] (p_1_1) [left =of dummy1] {$1$}; + \node[symbol_node] (a_1_2_2) [below left =of p_1_1] {$(1,a,2)$}; + \node[symbol_node] (b_2_3_3) [below right=of p_1_1] {$(2,b,3)$}; + \node[prod_node] (p_0_6) [right =of dummy2] {$0$}; + \node[symbol_node] (a_1_2_3) [below left =of p_0_6] {$(1,a,2)$}; + \node[symbol_node] (b_2_3_4) [below right=of p_0_6] {$(2,b,3)$}; + + + \path[->] + (s_2_2) edge (p_0_1) + + (p_0_1) edge (s_0_3) + (p_0_1) edge (a_2_0_1) + (p_0_1) edge (b_3_2_1) + + (s_0_3) edge (p_0_2) + + (p_0_2) edge (s_1_2) + (p_0_2) edge (a_0_1_1) + (p_0_2) edge (b_2_3_1) + + (s_1_2) edge (p_0_3) + + (p_0_3) edge (s_2_3) + (p_0_3) edge (a_1_2_1) + (p_0_3) edge (b_3_2_2) + + (s_2_3) edge (p_0_4) + + (p_0_4) edge (s_0_2) + (p_0_4) edge (a_2_0_2) + (p_0_4) edge (b_2_3_2) + + (s_0_2) edge (p_0_5) + + (p_0_5) edge (s_1_3) + (p_0_5) edge (a_0_1_2) + (p_0_5) edge (b_3_2_3) + + (s_1_3) edge (p_1_1) + + (p_1_1) edge (a_1_2_2) + (p_1_1) edge (b_2_3_3) + + (s_1_3) edge (p_0_6) + + (p_0_6) edge (a_1_2_3) + (p_0_6) edge (b_2_3_4) + (p_0_6) edge [bend right] (s_2_2) + + ; + \end{tikzpicture} + } + \end{center} + + Таким образом мы построили SPPF. Обойдя эту структуру необходимое количество раз, мы можем получить любой путь, удовлетворяющий условию. Более того, в полученном графе можно получать любые другие пути по соответствующим нетерминалам и парам вершин, содержащимся в узлах леса. + \end{example} + + \begin{note} + SPPF построенный для данной контекстно-свободной грамматики $G$ и графа $\mathcal{G}$ + \begin{enumerate} + \item содержит терминальный узел вида $(i,t_k,j)$ тогда и только тогда, когда в графе $\mathcal{G}$ есть ребро $(i,t_k,j)$; + \item содержит нетерминальный узел вида $(i,S_k,j)$ тогда и только тогда, когда в графе $\mathcal{G}$ есть путь из вершины $i$ в вершину $j$, выводимый из нетерминала $S_k$ в грамматике $G$. + \end{enumerate} + \end{note} + + Осталось увидеть, что SPPF является представлением контекстно-свободной грамматики, описывающей результат пересечения исходных графа и грамматики. Для этого просто построим грамматику $G_{\textit{SPPF}} = \langle \Sigma_{\textit{SPPF}}, N_{\textit{SPPF}}, S_{\textit{SPPF}}, P_{\textit{SPPF}}\rangle$ по SPPF следующим образом: + \begin{itemize} + \item $\Sigma_{\textit{SPPF}}$ --- все листья SPPF; + \item $N_{\textit{SPPF}}$ --- все нетерминальные узлы SPPF; + \item $S_{\textit{SPPF}}$ --- нетерминал, соответствующий пути, который нас будет интересовать; + \item $P_{\textit{SPPF}}$ --- для каждого дополнительного узла (с номером продукции) добавляем продукцию, левая часть которой --- непосредственный предок этого узла, а правая чать --- непосредственные потомки. + \end{itemize} + + \begin{example} + Построим грамматику для полученного SPPF: + \begin{align*} + (0)\ _2S_2 & \to\ _2a_0\ _0S_3\ _3b_2 &(4)\ _0S_2 \to\ &_0a_1\ _1S_3\ _3b_2 \\ + (1)\ _0S_3 & \to\ _0a_1\ _1S_2\ _2b_3 &(5)\ _1S_3 \to\ &_1a_2\ _2S_2\ _2b_3 \\ + (2)\ _1S_2 & \to\ _1a_2\ _2S_3\ _3b_2 &(6)\ _1S_3 \to\ &_1a_2\ _2b_3 \\ + (3)\ _2S_3 & \to\ _2a_0\ _0S_2\ _2b_3 & + \end{align*} + Видим, что для одного единственного нетерминала $_1S_3$ существует 2 правила, одно из которых рекурсивное. Попробуем получить левосторонний вывод какой-нибудь цепочки в этой грамматике: + \begin{align*} + & \boldsymbol{_2S_2} \xRightarrow{(0)\ } \\ + & {_2a_0}\ \boldsymbol{_0S_3}\ {_3b_2} \xRightarrow{(1)\ } \\ + & {_2a_0}\ {_0a_1}\ \boldsymbol{_1S_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(2)\ } \\ + & {_2a_0}\ {_0a_1}\ {_1a_2}\ \boldsymbol{_2S_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(3)\ } \\ + & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ \boldsymbol{_0S_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(4)\ } \\ + & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ \boldsymbol{_1S_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(5)\ } \\ + & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ \boldsymbol{_2S_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(0)\ } \\ + & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ \boldsymbol{_0S_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(1)\ } \\ + & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ \boldsymbol{_1S_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(2)\ } \\ + & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ \boldsymbol{_2S_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(3)\ } \\ + & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ \boldsymbol{_0S_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(4)\ } \\ + & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ \boldsymbol{_1S_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} \xRightarrow{(6)\ } \\ + & {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2a_0}\ {_0a_1}\ {_1a_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2}\ {_2b_3}\ {_3b_2} + \end{align*} + + Мы получили цепочку, которая действительно является путем из вершины 2 в вершину 2 в заданном графе. Таким образом выводятся и любые другие соответствующие пути. + +\end{example} + + +%\section{Вопросы и задачи} +%\begin{enumerate} +% \item Постройте дерево вывода цепочки $w=aababb$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ S \}, S \rangle$. +% \item Постройте все левосторонние выводы цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$. +% \item Постройте все правосторонние выводы цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$. +% \item \label{t1}Постройте все деревья вывода цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$, соответствующие левосторонним выводам. +% \item \label{t2}Постройте все деревья вывода цепочки $w=ababab$ в грамматике $G=\langle\{a,b\},\{S\},\{S\rightarrow \varepsilon \ | \ a \ S \ b \ | S \ S\}, S \rangle$, соответствующие правосторонним выводам. +% \item Как связаны между собой леса, полученные в предыдущих двух задачах (\ref{t1} и \ref{t2})? Какие выводы можно сделать из такой связи? +% \item Постройте сжатое представление леса разбора, полученного в задаче~\ref{t1}. +% \item Постройте сжатое представление леса разбора, полученного в задаче~\ref{t2}. +% \item \label{t3}Предъявите контекстно-свободную грамматику существенно неоднозначного языка. +% Возьмите цепочку длины болше пяти, при надлежащую этому языку, и постройте все деревья вывода этой цепочки в предъявленной грамматике. +% \item Постройте сжатое представление леса, полученного в задаче~\ref{t3}. +%\end{enumerate} diff --git a/tex/TensorProduct.tex b/tex/TensorProduct.tex new file mode 100644 index 0000000..8e13e86 --- /dev/null +++ b/tex/TensorProduct.tex @@ -0,0 +1,1366 @@ +\chapter{КС достижимость через тензорное произведение} + +Предыдущий подход позволяет выразить задачу поиска путей с ограничениями в терминах формальных языков через набор матричных операций. +Это позволяет использовать высокопроизводительные библиотеки, массовопараллельные архитектуры и другие готовые решения для линейной алгебры. +Однако, такой подход требует, чтобы грамматика находилась в ослабленной нормальной форме Хомского, что приводит к её разрастанию. +Можно ли как-то избежать этого? + +В данном разделе мы предложим альтернативное сведение задачи поиска путей к матричным операциям. +В результате мы сможем избежать преобразования грамматики в ОНФХ, однако, матрицы, с которыми нам предётся работать, будут существенно б\'{о}льшего размера. + +В основе подхода лежит использование рекурсивных сетей или рекурсивных автоматов в качестве представления контекстно-свободных грамматик и использование тензорного (прямого) произведения для нахождения пересечения автоматов. + + + +\section{Тензорное произведение} +\label{section2} + +Теперь перейдём к графам. +Сперва дадим классическое определение тензорного произведения двух неориентированных графов. + +\begin{definition} +Пусть даны два графа: $\mathcal{G}_1 = \langle V_1, E_1\rangle$ и $\mathcal{G}_2 = \langle V_2, E_2\rangle$. +Тензорным произведением этих графов будем называть граф $\mathcal{G}_3 = \langle V_3, E_3\rangle$, где $V_3 = V_1 \times V_2$, $E_3 = \{ ((v_1,v_2),(u_1,u_2)) \mid (v_1,u_1) \in E_1 \text{ и } (v_2,u_2) \in E_2 \}$. +\end{definition} + +Иными словами, тензорным произведением двух графов является граф, такой что: +\begin{enumerate} + \item множество вершин --- это прямое произведение множеств вершин исходных графов; + \item ребро между вершинами $v=(v_1,v_2)$ и $u=(u_1,u_2)$ существует тогда и только тогда, когда существуют рёбра между парами вершин $v_1$, $u_1$ и $v_2$, $u_2$ в соответствующих графах. +\end{enumerate} + +Для того, чтобы построить тензорное произведение ориентированных графов, необходимо в предыдущем определении, в условии существования ребра в результирующем графе, дополнительно потребовать, чтобы направления рёбер совпадали. +Данное требование получается естественным образом, если считать, что пары вершин, задающие ребро, упорядочены, поэтому формальное определение отличаться не будет. + +Осталось добавить метки к рёбрам. +Это приведёт к логичному усилению требования к существованию ребра: метки рёбер в исходных графах должны совпадать. +Таким образом, мы получаем следующее определение тензорного произведения ориентированных графов с метками на рёбрах. + +\begin{definition} +Пусть даны два ориентированных графа с метками на рёбрах: $\mathcal{G}_1 = \langle V_1, E_1, L_1 \rangle$ и $\mathcal{G}_2 = \langle V_2, E_2, L_2 \rangle$. +Тензорным произведением этих графов будем называть граф $\mathcal{G}_3 = \langle V_3, E_3, L_3\rangle$, где $V_3 = V_1 \times V_2$, $E_3 = \{ ((v_1,v_2),l,(u_1,u_2)) \mid (v_1,l,u_1) \in E_1 \text{ и } (v_2,l,u_2) \in E_2 \}$, $L_3=L_1 \cap L_2$. +\end{definition} + +Нетрудно заметить, что матрица смежности графа $\mathcal{G}_3$ равна тензорному произведению матриц смежностей исходных графов $\mathcal{G}_1$ и $\mathcal{G}_2$. + +\begin{example} +Рассмотрим пример. +В качестве одного из графов возьмём рекурсивный автомат, построенный ранее (изображение~\ref{input1}). +Его матрица смежности выглядит следующим образом. +\[ M_1 = +\begin{pmatrix} +. & [a] & . & . \\ +. & . & [S] & [b] \\ +. & . & . & [b] \\ +. & . & . & . +\end{pmatrix} +\] + +\begin{align} +\label{input2} + \input{figures/graph/graph0.tex} +\end{align} + +Второй граф представлен на изображении~\ref{input2}. +Его матрица смежности имеет следующий вид. +\[ M_2 = +\begin{pmatrix} +. & [a] & . & . \\ +. & . & [a] & . \\ +[a] & . & . & [b] \\ +. & . & [b] & . +\end{pmatrix} +\] + +Теперь вычислим $M_1 \otimes M_2$. +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +M_3 &= M_1 \otimes M_2 = +\begin{pmatrix} +. & [a] & . & . \\ +. & . & [S] & [b] \\ +. & . & . & [b] \\ +. & . & . & . +\end{pmatrix} +\otimes +\begin{pmatrix} +. & [a] & . & . \\ +. & . & [a] & . \\ +[a] & . & . & [b] \\ +. & . & [b] & . +\end{pmatrix} +=\notag\\ +&= +\label{eq:graph_tm} +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +\end{example} + +\section{Алгоритм} + +Идея алгоритма основана на обобщении пересечения двух конечных автоматов до пересечения рекурсивного автомата, построенного по грамматике, со входным графом. + +Пересечение двух конечных автоматов --- тензорное произведение соответствующих графов. +Пересечение языков коммутативно, тензорное произведение нет, но, как было сказано в замечании~\ref{note:KronIsNotCommutative}, существует решение этой проблемы. + +Будем рассматривать два конечных автомата: одни получен из входного графа, второй из грамматики. +Можно найти их пересечение, вычислив тензорное произведение матриц смежности соответствующих графов. +Однако, одной такой итерации не достаточно для решения исходной задачи. За первую итерацию мы найдём только те пути, которые выводятся в грамматике за одни шаг. После этого необходимо добавить соответствующие рёбра во входной граф и повторить операцию: так мы найдём пути, выводимые за два шага. Данные действия надо повторять до тех пор, пока не перестанут находиться новые пары достижимых вершин. +Псевдокод, описывающий данные действия, представлен в листинге~\ref{lst:algo1}. + +\begin{algorithm} + \floatname{algorithm}{Listing} +\begin{algorithmic}[1] +\caption{Поиск путей через тензорное произведение} +\label{lst:algo1} +\Function{contextFreePathQueryingTP}{G, $\mathcal{G}$} + \State{$R \gets$ рекурсивный автомат для $G$} + \State{$N \gets$ нетерминальный алфавит для $R$} + \State{$S \gets$ стартовые состояния для $R$} + \State{$F \gets$ конечные состояния для $R$} + \State{$M_1 \gets$ матрица смежности $R$} + \State{$M_2 \gets$ матрица смежности $\mathcal{G}$} + \For{$N_i \in N$} + \If{$N_i \xrightarrow{*} \varepsilon$} + \State{for all $j \in \mathcal{G}.V: M_2[j,j] \gets M_2[j,j] \cup \{N_i\}$} + \Comment{Добавим петли для нетерминалов, выводящих $\varepsilon$} + \EndIf + \EndFor + \While{матрица $M_2$ изменяется} + \State{$M_3 \gets M_1 \otimes M_2$} + \Comment{Пересечение графов} + \State{$tC_3 \gets \textit{transitiveClosure}(M_3)$} + \State{$n \gets$ количество строк и столбцов матрицы $M_3$} + \Comment{размер матрицы $M_3$ = $n \times n$} + \For{$i \in 0..n$} + \For{$j \in 0..n$} + \If{$tC_3[i,j]$} + \State{$s \gets$ стартовая вершина ребра $tC_3[i,j]$} + \State{$f \gets$ конечная вершина ребра $tC_3[i,j]$} + \If{$s \in S$ and $f \in F$ } + \State{$x, y \gets$ $getCoordinates(i,j)$} + \State{$M_2[x,y] \gets M_2[x,y] \cup \{getNonterminals(s,f)\}$} + \EndIf + \EndIf + \EndFor + \EndFor + \EndWhile +\State \Return $M_2$ +\EndFunction +\end{algorithmic} +\end{algorithm} + + +Алгоритм исполняется до тех пор, пока матрица смежности $M_2$ изменяется. +На каждой итерации цикла алгоритм последовательно проделывает следующие команды: пересечение двух автоматов через тензорное произведение, транзитивное замыкание результата тензорного произведения и итерация по всем ячейкам получившейся после транзитивного замыкания матрицы, что необходимо для поиска новых пар достижимых вершин. +Во время итерации по ячейкам матрицы транзитивного замыкания алгоритм сначала проверяет наличие ребра в данной ячейке, а затем --- принадлежность стартовой и конечной вершин ребра к стартовому и конечному состоянию входного рекурсивного автомата. +При удовлетворении этих условий алгоритм добавляет нетерминал (или нетерминалы), соответствующие стартовой и конечной вершинам ребра, в ячейку матрицы $M_2$, полученной при помощи функции $getCoordinates(i,j)$. + +Представленный алгоритм не требует преобразования грамматики в ОНФХ, более того, рекурсивный автомат может быть минимизирован. Однако, результатом тензорного рпоизведения является матрица существенно б\'{о}льшего размера, чем в алгоритме, основанном на матричном рпоизведении. +Кроме этого, необходимо искать транзитивное замыкание этой матрицы. + +Ещё одним важным свойством представленного алгоритма является его оптимальность при обработке регулярных запросов. +Так как по контекстно свободной грамматике мы не можем определить, задаёт ли она регулярный язык, то при добавлении в язык запросов возможности задавать контекстно-свободные ограничения, возникает проблема: мы не можем в общем случае отличить регулярный запрос от контекстно-свободного. Следовательно, мы вынуждены применять наиболее общий механизм выполнения заросов, что может приводить к существенным накладным расходам при выполнении регулярного запроса. +Данный же алгоритм не выполнит лишних действий, так как сразу выполнит классическое пересечение двух автоматов и получит результат. + +\section{Примеры} + +Рассмотрим подробно ряд примеров работы описанного алгоритма. +Будем для каждой итерации внешнего цикла выписывать результаты основных операций: тензорного произведения, транзитивного замыкания, обновления матрицы смежности входного графа. +Новые, по сравнению с предыдущим состоянием, элементы матриц будем выделять. + +\begin{example} +\label{algorithm_example} +Теоретически худший случай. +Такой же как и для матричного. + +\textbf{Итерация 1 (конец).} Начало в разделе~\ref{section2}, где мы вычислили тензорное произведение матриц смежности. +Теперь нам осталось только вычислить транзитивное замыкание полученной матрицы: + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +tc(M_3) = +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & .\\ +. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & \bfgray{[ab]} \\ +. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right). +\end{scaledalign} + +Мы видим, что в результате транзитивного замыкания появилось новое ребро с меткой $ab$ из вершины $(0,1)$ в вершину $(3,3)$. +Так как вершина 0 является стартовой в рекурсивном автомате, а 3 является финальной, то слово вдоль пути из вершины 1 в вершину 3 во входном графе выводимо из нетерминала $S$. +Это означает, что в графе должно быть добавлено ребро из $0$ в $3$ с меткой $S$, после чего граф будет выглядеть следующим образом: + +\begin{center} + \input{figures/tensor/graph0.tex} +\end{center} + +Матрица смежности обновлённого графа: +\[ M_2 = +\begin{pmatrix} +. & [a] & . & . \\ +. & . & [a] & \textbf{[S]} \\ +[a] & . & . & [b] \\ +. & . & [b] & . +\end{pmatrix} +\] + +Итерация закончена. +Возвращаемся к началу цикла и вновь вычисляем тензорное произведение. + +\textbf{Итерация 2.} +Вычисляем тензорное произведение матриц смежности. + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +M_3 &= M_1 \otimes M_2 = +\begin{pmatrix} +. & [a] & . & . \\ +. & . & [S] & [b] \\ +. & . & . & [b] \\ +. & . & . & . +\end{pmatrix} +\otimes +\begin{pmatrix} +. & [a] & . & . \\ +. & . & [a] & [S] \\ +[a] & . & . & [b] \\ +. & . & [b] & . +\end{pmatrix} +=\notag\\ +&= +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & \bfgray{[S]} & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Вычисляем транзитивное замыкание полученной матрицы: + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +tc(M_3) = +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & . & \bfgray{[aS]} & . & . & \bfgray{[aSb]} & . \\ +. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & [ab] \\ +. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & \bfgray{[Sb]} & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +В транзитивном замыкании появилось три новых ребра, однако только одно из них соединяет вершины, соответствующие стартовому и конечному состоянию входного рекурсивного автомата. +Таким образом только это ребро должно быть добавлено во входной граф. +В итоге, обновлённый граф: +\begin{center} +\input{figures/tensor/graph1.tex} +\end{center} + +И его матрица смежности: +\[ M_2 = +\begin{pmatrix} +. & [a] & [S] & . \\ +. & . & [a] & [S] \\ +[a] & . & . & [b] \\ +. & . & [b] & . +\end{pmatrix} +\] +\textbf{Итерация 3.} +Снова начинаем с тензорного произведения. + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +M_3 &= M_1 \otimes M_2 = +\begin{pmatrix} +. & [a] & . & . \\ +. & . & [S] & [b] \\ +. & . & . & [b] \\ +. & . & . & . +\end{pmatrix} +\otimes +\begin{pmatrix} +. & [a] & [S] & . \\ +. & . & [a] & [S] \\ +[a] & . & . & [b] \\ +. & . & [b] & . +\end{pmatrix} +=\notag\\ +&= +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & \bfgray{[S]} & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Затем вычисляем транзитивное замыкание: + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +tc(M_3) = +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & . & [aS] & . & . & [aSb] & . \\ +. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & [ab] \\ +. & . & . & . & [a] & . & . & . & . & . & \bfgray{[aS]} & . & . & . & . & \bfgray{[aSb]} \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & \bfgray{[Sb]} \\ +. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & [Sb] & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +И наконец обновляем граф: +\begin{center} +\input{figures/tensor/graph2.tex} +\end{center} + +Матрица смежности обновлённого графа: +\[ M_2 = +\begin{pmatrix} +. & [a] & [S] & . \\ +. & . & [a] & [S] \\ +[a] & . & . & [b, \textbf{S}] \\ +. & . & [b] & . +\end{pmatrix} +\] +Уже можно заметить закономерность: на каждой итерации мы добавляем ровно одно новое ребро во входной граф, ровно как и в алгоритме, основанном на матричном произведении, и как в алгоритме Хеллингса. +То есть находим ровно одну новую пару вершин, между которыми существует интересующий нас путь. +Попробуйте спрогнозировать, сколько итераций нам ещё осталось сделать. + +\textbf{Итерауия 4}. +Продолжаем. Вычисляем тензорное произведение. + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +M_3 &= M_1 \otimes M_2 = +\begin{pmatrix} +. & [a] & . & . \\ +. & . & [S] & [b] \\ +. & . & . & [b] \\ +. & . & . & . +\end{pmatrix} +\otimes +\begin{pmatrix} +. & [a] & [S] & . \\ +. & . & [a] & [S] \\ +[a] & . & . & [b,S] \\ +. & . & [b] & . +\end{pmatrix} +=\notag\\ +&= +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & \bfgray{[S]} & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Затем транзитивное замыкание: + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +tc(M_3) = +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & . & [aS] & . & . & [aSb] & . \\ +. & . & . & . & . & . & [a] & . & . & . & . & \bfgray{[aS]} & . & . & \bfgray{[aSb]} & [ab] \\ +. & . & . & . & [a] & . & . & . & . & . & [aS] & . & . & . & . & [aSb] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & [Sb] \\ +. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & [Sb] & . \\ +. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & \bfgray{[Sb]} & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +И снова обновляем граф, так как в транзитивном замыкании появился один (и снова ровно один) новый элемент, соответствующий принимающему пути в автомате. +\begin{center} +\input{figures/tensor/graph3.tex} +\end{center} + + +Матрица смежности обновлённого графа: +\[ M_2 = +\begin{pmatrix} +. & [a] & [S] & . \\ +. & . & [a, \textbf{S}] & [S] \\ +[a] & . & . & [b,S] \\ +. & . & [b] & . +\end{pmatrix} +\] +\textbf{Итерация 5.} +Приступаем к выполнению следующей итерации основного цикла. +Вычисляем тензорное произведение. + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +M_3 &= M_1 \otimes M_2 = +\begin{pmatrix} +. & [a] & . & . \\ +. & . & [S] & [b] \\ +. & . & . & [b] \\ +. & . & . & . +\end{pmatrix} +\otimes +\begin{pmatrix} +. & [a] & [S] & . \\ +. & . & [a,S] & [S] \\ +[a] & . & . & [b,S] \\ +. & . & [b] & . +\end{pmatrix} +=\notag\\ +&= +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & \bfgray{[S]} & [S] & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Затем вычисляем транзитивное замыкание: + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +tc(M_3) = +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & \bfgray{[aS]} & [aS] & . & . & [aSb] & \bfgray{[aSb]} \\ +. & . & . & . & . & . & [a] & . & . & . & . & [aS] & . & . & [aSb] & [ab] \\ +. & . & . & . & [a] & . & . & . & . & . & [aS] & . & . & . & . & [aSb] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & [Sb] \\ +. & . & . & . & . & . & . & . & . & . & [S] & [S] & . & . & [Sb] & \bfgray{[Sb]} \\ +. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & [Sb] & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Обновляем граф: +\begin{center} + \input{figures/tensor/graph4.tex} +\end{center} + + +Матрица смежности обновлённого графа: +\[ M_2 = +\begin{pmatrix} +. & [a] & [S] & \textbf{[S]} \\ +. & . & [a, S] & [S] \\ +[a] & . & . & [b,S] \\ +. & . & [b] & . +\end{pmatrix} +\] +\textbf{Итерация 6.} +И наконец последняя содержательная итерация основного цикла. + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +M_3 &= M_1 \otimes M_2 = +\begin{pmatrix} +. & [a] & . & . \\ +. & . & [S] & [b] \\ +. & . & . & [b] \\ +. & . & . & . +\end{pmatrix} +\otimes +\begin{pmatrix} +. & [a] & [S] & [S] \\ +. & . & [a,S] & [S] \\ +[a] & . & . & [b,S] \\ +. & . & [b] & . +\end{pmatrix} +=\\ +&= +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & [S] & \bfgray{[S]} & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & [S] & [S] & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Транзитивное замыкание: + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +tc(M_3) = +\left(\begin{array}{c c c c | c c c c | c c c c | c c c c } +. & . & . & . & . & [a] & . & . & . & . & [aS] & [aS] & . & . & [aSb] & [aSb] \\ +. & . & . & . & . & . & [a] & . & . & . & . & [aS] & . & . & [aSb] & [ab] \\ +. & . & . & . & [a] & . & . & . & . & . & [aS] & \bfgray{[aS]} & . & . & \bfgray{[aSb]} & [aSb] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & [S] & \bfgray{[S]} & . & . & \bfgray{[Sb]} & [Sb] \\ +. & . & . & . & . & . & . & . & . & . & [S] & [S] & . & . & [Sb] & [Sb] \\ +. & . & . & . & . & . & . & . & . & . & . & [S] & . & . & [Sb] & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Обновлённый граф: +\begin{center} +\input{figures/tensor/graph5.tex} +\end{center} + + +И матрица смежности: +\[ M_2 = +\begin{pmatrix} +. & [a] & [S] & [S] \\ +. & . & [a, S] & [S] \\ +[a] & . & \textbf{[S]} & [b,S] \\ +. & . & [b] & . +\end{pmatrix} +\] +Следующая итерация не приведёт к изменению графа. +Читатель может убедиться в этом самостоятельно. +Соответственно, алгоритм можно завершать. +Нам потребовалось семь итераций (шесть содержательных и одна проверочная), на каждой из которых вычисляются тензорное произведение двух матриц смежности и транзитивное замыкание результата. + +Матрица смежности получилась такая же, как и раньше, ответ правильный. +Мы видим, что количество итераций внешнего цикла такое же как и у алгоритма CYK (пример~\ref{CYK_algorithm_ex}). + +\end{example} + + +\begin{example} + +В данном примере мы увидим, как структура грамматики и, соответственно, рекурсивного автомата, влияет на процесс вычислений. + +Интуитивно понятно, что чем меньше состояний в рекурсивной сети, тем лучше. +То есть желательно получить как можно более компактное описание контекстно-свободного языка. + +Для примера возьмём в качестве КС языка язык Дика на одном типе скобок и опишем его двумя различными грамматиками. +Первая грамматика классическая: +\[ +G_1 = \langle \{a,\ b\}, \{ S \}, \{S \to a \ S \ b \ S \mid \varepsilon \} \rangle +\] +Во второй грамматике мы будем использовать конструкции регулярных выражений в правой части правил. +То есть вторая грамматика находится в EBNF (Расширенная форма Бэкуса-Наура~\cite{Hemerik2009, Wirth1977}). +\[ +G_2 = \langle \{a, \ b\}, \{S\}, \{S \to (a \ S \ b)^{*}\} \rangle +\] +Построим рекурсивные автоматы $N_1$ и $N_2$ и их матрицы смежности для этих грамматик. + +Рекурсивный автомат $N_1$ для грамматики $G_1$: +\begin{center} +\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] + \node[state, initial, accepting] (q_0) {$0$}; + \node[state] (q_1) [right=of q_0] {$1$}; + \node[state] (q_2) [right=of q_1] {$2$}; + \node[state] (q_3) [right=of q_2] {$3$}; + \node[state, accepting] (q_4) [right=of q_3] {$4$}; + \path[->] + (q_0) edge node {a} (q_1) + (q_1) edge node {S} (q_2) + (q_2) edge node {b} (q_3) + (q_3) edge node {S} (q_4); +\end{tikzpicture} +\end{center} + +Матрица смежности $N_1$: +\[ +M_1^1 = +\begin{pmatrix} +. & [a] & . & . & . \\ +. & . & [S] & . & . \\ +. & . & . & [b] & . \\ +. & . & . & . & [S] \\ +. & . & . & . & . +\end{pmatrix} +\] +Рекурсивный автомат $N_2$ для грамматики $G_2$: +\begin{center} + \input{figures/tensor/recursive.tex} +\end{center} + +Матрица смежности $N_2$: +\[ +M_1^2 = +\begin{pmatrix} +. & [a] & . \\ +. & . & [S] \\ +[b] & . & . +\end{pmatrix} +\] +Первое очевидное наблюдение --- количество состояний в $N_2$ меньше, чем в $N_1$. +Это значит, что матрица смежности, а значит, и результат тензорного произведения будут меньше, следовательно, вычисления будут производиться быстрее. + +Выполним пошагово алгоритм для двух заданных рекурсивных сетей на линейном входе: +\begin{center} +\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] + \node[state] (q_0) {$0$}; + \node[state] (q_1) [right=of q_0] {$1$}; + \node[state] (q_2) [right=of q_1] {$2$}; + \node[state] (q_3) [right=of q_2] {$3$}; + \node[state] (q_4) [right=of q_3] {$4$}; + \node[state] (q_5) [right=of q_4] {$5$}; + \node[state] (q_6) [right=of q_5] {$6$}; + \path[->] + (q_0) edge node {a} (q_1) + (q_1) edge node {b} (q_2) + (q_2) edge node {a} (q_3) + (q_3) edge node {b} (q_4) + (q_4) edge node {a} (q_5) + (q_5) edge node {b} (q_6); +\end{tikzpicture} +\end{center} + + +Сразу дополним матрицу смежности нетерминалами, выводящими пустую строку, и получим следующую матрицу: +\begin{scaledalign}{\footnotesize}{0.5pt}{0.9}{\notag} +M_2 = +\begin{pmatrix} +[S] & [a] & . & . & . & . & . \\ +. & [S] & [b] & . & . & . & . \\ +. & . & [S] & [a] & . & . & . \\ +. & . & . & [S] & [b] & . & . \\ +. & . & . & . & [S] & [a] & . \\ +. & . & . & . & . & [S] & [b] \\ +. & . & . & . & . & . & [S] +\end{pmatrix} +\end{scaledalign} + +Сперва запустим алгоритм на данном входе и $N_2$. +Первый шаг первой итерации --- вычисление тензорного произведения $M_1^2 \otimes M_2$. + +\begin{scaledalign}{\footnotesize}{2pt}{0.9}{\notag} +M_3 &= M_1^2 \otimes M_2 = +\begin{pmatrix} +. & [a] & . \\ +. & . & [S] \\ +[b] & . & . +\end{pmatrix} +\otimes +\begin{pmatrix} +[S] & [a] & . & . & . & . & . \\ +. & [S] & [b] & . & . & . & . \\ +. & . & [S] & [a] & . & . & . \\ +. & . & . & [S] & [b] & . & . \\ +. & . & . & . & [S] & [a] & . \\ +. & . & . & . & . & [S] & [b] \\ +. & . & . & . & . & . & [S] +\end{pmatrix} +=\notag\\ +&= +\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c } +. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + + +\newcommand{\tinybf}[1]{\cellcolor{lightgray}\textbf{\tiny{[#1]}}} +\newcommand{\tntm}[1]{\text{\tiny{#1}}} + +Опустим промежуточные шаги вычисления транзитивного замыкания $M_3$ и сразу представим конечный результат: +\begin{scaledalign}{\footnotesize}{0.5pt}{0.5}{\notag} +&tc(M_3)= +\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c } +. & . & \tinybf{aSb} & . & \tinybf{aSbaSb} & . & \tinybf{aSbaSbaSb} & . & [a] & . & \tinybf{aSba} & . & \tinybf{aSbaSba} & . & . & \tinybf{aS} & . & \tinybf{aSbaS} & . & \tinybf{aSbaSbaS} & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & \tinybf{aSb} & . & \tinybf{aSbaSb} & . & . & . & [a] & . & \tinybf{aSba} & . & . & . & . & \tinybf{aS} & . & \tinybf{aSbaS} & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & \tinybf{aSb} & . & . & . & . & . & [a] & . & . & . & . & . & . & \tinybf{aS} & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +В результате вычисления транзитивного замыкания появилось большое количество новых рёбер, однако нас будут интересовать только те, информация о которых храниться в левом верхнем блоке. +Остальные рёбра не соответствуют принимающим путям в рекурсивном автомате (убедитесь в этом самостоятельно). + +После добавления соответствующих рёбер, мы получим следующий граф: +\begin{center} +\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] + \node[state] (q_0) {$0$}; + \node[state] (q_1) [right=of q_0] {$1$}; + \node[state] (q_2) [right=of q_1] {$2$}; + \node[state] (q_3) [right=of q_2] {$3$}; + \node[state] (q_4) [right=of q_3] {$4$}; + \node[state] (q_5) [right=of q_4] {$5$}; + \node[state] (q_6) [right=of q_5] {$6$}; + \path[->] + (q_0) edge node {a} (q_1) + (q_0) edge[bend left, above] node {\textbf{S}} (q_2) + (q_0) edge[bend right, above] node {\textbf{S}} (q_4) + (q_0) edge[bend right, above] node {\textbf{S}} (q_6) + (q_1) edge node {b} (q_2) + (q_2) edge node {a} (q_3) + (q_2) edge[bend left, above] node {\textbf{S}} (q_4) + (q_2) edge[bend right, above] node {\textbf{S}} (q_6) + (q_3) edge node {b} (q_4) + (q_4) edge node {a} (q_5) + (q_4) edge[bend left, above] node {\textbf{S}} (q_6) + (q_5) edge node {b} (q_6); +\end{tikzpicture} +\end{center} + + +Его матрица смежности: + +\begin{scaledalign}{\footnotesize}{0.5pt}{0.9}{\notag} +M_2 = +\begin{pmatrix} +[S] & [a] & \bfgray{[S]} & . & \bfgray{[S]} & . & \bfgray{[S]} \\ +. & [S] & [b] & . & . & . & . \\ +. & . & [S] & [a] & \bfgray{[S]} & . & \bfgray{[S]} \\ +. & . & . & [S] & [b] & . & . \\ +. & . & . & . & [S] & [a] & \bfgray{[S]} \\ +. & . & . & . & . & [S] & [b] \\ +. & . & . & . & . & . & [S] +\end{pmatrix} +\end{scaledalign} + +Таким образом видно, что для выбранных входных данных алгоритму достаточно двух итераций основного цикла: первая содержательная, вторая, как обычно, проверочная. +Читателю предлагается самостоятельно выяснить, сколько умножений матриц потребуется, чтобы вычислить транзитивное замыкание на первой итерации. + +Теперь запустим алгоритм на второй грамматике и том же входе. + +\begin{scaledalign}{\footnotesize}{0.5pt}{0.8}{\notag} +&M_3 = M_1^1 \otimes M_2 = +\begin{pmatrix} +. & [a] & . & . & . \\ +. & . & [S] & . & . \\ +. & . & . & [b] & . \\ +. & . & . & . & [S] \\ +. & . & . & . & . +\end{pmatrix} +\otimes +\begin{pmatrix} +[S] & [a] & . & . & . & . & . \\ +. & [S] & [b] & . & . & . & . \\ +. & . & [S] & [a] & . & . & . \\ +. & . & . & [S] & [b] & . & . \\ +. & . & . & . & [S] & [a] & . \\ +. & . & . & . & . & [S] & [b] \\ +. & . & . & . & . & . & [S] +\end{pmatrix} +=\notag\\ +&= +\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} +. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Уже сейчас можно заметить, что размер матриц, с которыми нам придётся работать, существенно увеличился, по сравнению с предыдущим вариантом. +Это, конечно, закономерно, ведь в рекурсивном автомате для предыдущего варианта меньше состояний, а значит и матрица смежности имеет меньший размер. + +Транзитивное замыкание: +\begin{scaledalign}{\footnotesize}{0.3pt}{0.5}{\notag} +&tc(M_3)= +\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} +. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tinybf{aS} & . & . & . & . & . & . & . & \tinybf{aSb} & . & . & . & . & . & . & \tinybf{aSbS} & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tinybf{aS} & . & . & . & . & . & . & . & \tinybf{aSb} & . & . & . & . & . & . & \tinybf{aSbS} & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tinybf{aS} & . & . & . & . & . & . & . & \tinybf{aSb} & . & . & . & . & . & . & \tinybf{aSbS} \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Обновлённый граф: +\begin{center} +\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] + \node[state] (q_0) {$0$}; + \node[state] (q_1) [right=of q_0] {$1$}; + \node[state] (q_2) [right=of q_1] {$2$}; + \node[state] (q_3) [right=of q_2] {$3$}; + \node[state] (q_4) [right=of q_3] {$4$}; + \node[state] (q_5) [right=of q_4] {$5$}; + \node[state] (q_6) [right=of q_5] {$6$}; + \path[->] + (q_0) edge node {a} (q_1) + (q_0) edge[bend left, above] node {\textbf{S}} (q_2) + (q_1) edge node {b} (q_2) + (q_2) edge node {a} (q_3) + (q_2) edge[bend left, above] node {\textbf{S}} (q_4) + (q_3) edge node {b} (q_4) + (q_4) edge node {a} (q_5) + (q_4) edge[bend left, above] node {\textbf{S}} (q_6) + (q_5) edge node {b} (q_6); +\end{tikzpicture} +\end{center} + + +Его матрица смежности: + +\begin{scaledalign}{\footnotesize}{0.5pt}{0.9}{\notag} +M_2 = +\begin{pmatrix} +[S] & [a] & \bfgray{[S]} & . & . & . & . \\ +. & [S] & [b] & . & . & . & . \\ +. & . & [S] & [a] & \bfgray{[S]} & . & . \\ +. & . & . & [S] & [b] & . & . \\ +. & . & . & . & [S] & [a] & \bfgray{[S]} \\ +. & . & . & . & . & [S] & [b] \\ +. & . & . & . & . & . & [S] +\end{pmatrix} +\end{scaledalign} + +Потребуется ещё одна итерация. + +\begin{scaledalign}{\footnotesize}{0.5pt}{0.8}{\notag} +&M_3 = M_1^1 \otimes M_2 = +\begin{pmatrix} +. & [a] & . & . & . \\ +. & . & [S] & . & . \\ +. & . & . & [b] & . \\ +. & . & . & . & [S] \\ +. & . & . & . & . +\end{pmatrix} +\otimes +\begin{pmatrix} +[S] & [a] & [S] & . & . & . & . \\ +. & [S] & [b] & . & . & . & . \\ +. & . & [S] & [a] & [S] & . & . \\ +. & . & . & [S] & [b] & . & . \\ +. & . & . & . & [S] & [a] & [S] \\ +. & . & . & . & . & [S] & [b] \\ +. & . & . & . & . & . & [S] +\end{pmatrix} +=\notag\\ +&= +\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} +. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & \bfgray{[S]} \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Транзитивное замыкание: +\begin{scaledalign}{\footnotesize}{0.3pt}{0.5}{\notag} +&tc(M_3)= +\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} +. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & \tinybf{aS} & . & . & . & . & . & \tntm{[aSb]} & . & \tinybf{aSb} & . & . & . & . & \tntm{[aSbS]} & . & \tinybf{aSbS} & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & \tinybf{aS} & . & . & . & . & . & \tntm{[aSb]} & . & \tinybf{aSb} & . & . & . & . & \tntm{[aSbS]} & . & \tinybf{aSbS} \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & . & . & . & . & . & . & \tntm{[aSb]} & . & . & . & . & . & . & \tntm{[aSbS]} \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Обновлённый граф: +\begin{center} +\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] + \node[state] (q_0) {$0$}; + \node[state] (q_1) [right=of q_0] {$1$}; + \node[state] (q_2) [right=of q_1] {$2$}; + \node[state] (q_3) [right=of q_2] {$3$}; + \node[state] (q_4) [right=of q_3] {$4$}; + \node[state] (q_5) [right=of q_4] {$5$}; + \node[state] (q_6) [right=of q_5] {$6$}; + \path[->] + (q_0) edge node {a} (q_1) + (q_0) edge[bend left, above] node {S} (q_2) + (q_0) edge[bend right, above] node {\textbf{S}} (q_4) + (q_1) edge node {b} (q_2) + (q_2) edge node {a} (q_3) + (q_2) edge[bend left, above] node {S} (q_4) + (q_2) edge[bend right, above] node {\textbf{S}} (q_6) + (q_3) edge node {b} (q_4) + (q_4) edge node {a} (q_5) + (q_4) edge[bend left, above] node {S} (q_6) + (q_5) edge node {b} (q_6); +\end{tikzpicture} +\end{center} + +На этом шаге мы смогли ``склеить'' из подстрок, выводимых из $S$, более длинные пути. +Однако, согласно правилам грамматики, мы смогли ``склеить'' только две подстроки в единое целое. + +Матрица смежности обновлённого графа: + +\begin{scaledalign}{\footnotesize}{0.5pt}{0.9}{\notag} +M_2 = +\begin{pmatrix} +[S] & [a] & [S] & . & \bfgray{[S]} & . & \\ +. & [S] & [b] & . & . & . & . \\ +. & . & [S] & [a] & [S] & . & \bfgray{[S]} \\ +. & . & . & [S] & [b] & . & . \\ +. & . & . & . & [S] & [a] & [S] \\ +. & . & . & . & . & [S] & [b] \\ +. & . & . & . & . & . & [S] +\end{pmatrix} +\end{scaledalign} + +И, наконец, последняя содержательная итерация. + +\begin{scaledalign}{\footnotesize}{0.5pt}{0.8}{\notag} +&M_3 = M_1^1 \otimes M_2 = +\begin{pmatrix} +. & [a] & . & . & . \\ +. & . & [S] & . & . \\ +. & . & . & [b] & . \\ +. & . & . & . & [S] \\ +. & . & . & . & . +\end{pmatrix} +\otimes +\begin{pmatrix} +[S] & [a] & [S] & . & [S] & . & . \\ +. & [S] & [b] & . & . & . & . \\ +. & . & [S] & [a] & [S] & . & [S] \\ +. & . & . & [S] & [b] & . & . \\ +. & . & . & . & [S] & [a] & [S] \\ +. & . & . & . & . & [S] & [b] \\ +. & . & . & . & . & . & [S] +\end{pmatrix} +=\notag\\ +&= +\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} +. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & \bfgray{[S]} & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & \bfgray{[S]} & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & \bfgray{[S]} & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & \bfgray{[S]} \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + +Транзитивное замыкание: +\begin{scaledalign}{\footnotesize}{0.3pt}{0.5}{\notag} +&tc(M_3)= +\left(\begin{array}{c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c | c c c c c c c} +. & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & \tntm{[aS]} & . & \tinybf{aS} & . & . & . & \tntm{[aSb]} & . & \tntm{[aSb]} & . & \tinybf{aSb} & . & . & \tntm{[aSbS]} & . & \tntm{[aSbS]} & . & \tinybf{aSbS} \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & \tntm{[aS]} & . & . & . & . & . & \tntm{[aSb]} & . & \tntm{[aSb]} & . & . & . & . & \tntm{[aSbS]} & . & \tntm{[aSbS]} \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & [a] & . & . & . & . & . & . & \tntm{[aS]} & . & . & . & . & . & . & . & \tntm{[aSb]} & . & . & . & . & . & . & \tntm{[aSbS]} \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [b] & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & [S] & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] & . & [S] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . & [S] \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & [S] \\ +\hline +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . & . +\end{array}\right) +\end{scaledalign} + + +В конечном итоге мы получаем такой же результат, как и при первом запуске. +Однако нам потребовалось выполнить существенно больше итераций внешнего цикла, а именно четыре (три содержательных и одна проверочная). +При этом, в ходе работы нам пришлось оперировать существенно б\'{о}льшими матрицами: $35 \times 35$ против $21 \times 21$. + +Таким образом, видно, что минимизация представления запроса, в частности, минимизация рекурсивного автомата как конечного автомата над смешанным алфавитом может улучшить производительность выполнения запросов. +\end{example} + +\section{Особенности реализации} + +Как и алгоритмы, представленные в разделе~\ref{chpt:MatrixBasedAlgos}, представленный здесь алгоритм оперирует разреженными матрицами, поэтому, к нему применимы все те же соображения, что и к алгоритмам, основанным на произведении матриц. Более того, так как результат тензорного произведения является блочной матрицей, то могут оказаться полезными различные форматы для хранения блочно-разреженных матриц. Вместе с этим, в некоторых случаях матрицу смежности рекурсивного автомата удобнее представлять в классическом, плотном, виде, так как для некоторых запросов её размер мал и накладные расходы на представление в разреженном формате и работе с ним будут больше, чем выигрыш от его использования. + + +Также заметим, что блочная структура матриц даёт хорошую основу для распределённого умножения матриц при построении транзитивного замыкания. + +Вместо того, чтобы перезаписывать каждый раз матрицу смежности входного графа $M_2$ можно вычислять только разницу с предыдущим шагом. +Для этого, правда, потребуется хранить в памяти ещё одну матрицу. +Поэтому нужно проверять, что вычислительно дешевле: поддерживать разницу и потом каждый раз поэлементно складывать две матрицы или каждый раз вычислять полностью произведение. + +Заметим, что для решения задачи достижимости нам не нужно накапливать пути вдоль рёбер, как мы это делали в примерах, соответственно, во-первых, можно переопределить тензорное произведение так, чтобы его результатом являлась булева матрица, во-вторых, как следствие первого изменеия, транзитивное замыкание для булевой матрицы можно искать с применением соответствующих оптимизаций. + +%\section{Вопросы и задачи} +% +%\begin{enumerate} +% \item Оценить пространсвенную сложность алгоритма. +% \item Оценить временную сложность алгоритма. +% \item Найти библиотеку для тензорного произведения. Реализовать алгоритм. Можно предпологать, что запросы содержат ограниченное число терминалов и нетерминалов. Провести замеры. Сравнить с матричным. +% \item Реализовать распределённое решение. +%См. блочную структуру +%\end{enumerate} diff --git a/tex/figures/GLR/CLR_example.tex b/tex/figures/GLR/CLR_example.tex new file mode 100644 index 0000000..8f06101 --- /dev/null +++ b/tex/figures/GLR/CLR_example.tex @@ -0,0 +1,99 @@ +\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] + \node[r_state] (s_0) + { + $ + \begin{aligned} + S' &\to \cdot S, \{\$\} \\ + S &\to \cdot a S b S, \{\$\} \\ + S &\to \cdot, \{\$\} + \end{aligned} + $ + }; + \node[r_state] (s_1) [below=2.5cm of s_0] + { + $ + \begin{aligned} + S &\to a \cdot S b S, \{\$\} \\ + S &\to \cdot a S b S, \{b\} \\ + S &\to \cdot, \{b\} + \end{aligned} + $ + }; + \node[r_state] (s_2) [below=2.5cm of s_1] + { + $ + \begin{aligned} + S &\to a \cdot S b S, \{b\} \\ + S &\to \cdot a S b S, \{b\} \\ + S &\to \cdot, \{b\} + \end{aligned} + $ + }; + \node[r_state] (s_3) [right=of s_0] + { + $ S' \to S \cdot, \{\$\} $ + }; + \node[r_state] (s_4) [right=of s_1] + { + $ S \to a S \cdot b S, \{\$\} $ + }; + \node[r_state] (s_5) [right=of s_2] + { + $ S \to a S \cdot b S, \{b\} $ + }; + \node[r_state] (s_6) [right=of s_4] + { + $ + \begin{aligned} + S &\to a S b \cdot S, \{\$\} \\ + S &\to \cdot a S b S, \{\$\} \\ + S &\to \cdot, \{\$\} + \end{aligned} + $ + }; + \node[r_state] (s_7) [right=of s_5] + { + $ + \begin{aligned} + S &\to a S b \cdot S, \{b\} \\ + S &\to \cdot a S b S, \{b\} \\ + S &\to \cdot , \{b\} + \end{aligned} + $ + }; + \node[r_state] (s_8) [right=of s_6] + { + $ S \to a S b S \cdot, \{\$\} $ + }; + \node[r_state] (s_9) [right=of s_7] + { + $ S \to a S b S \cdot, \{b\} $ + }; + + \node[num_state] at (s_0.north west) {0}; + \node[num_state] at (s_1.north west) {1}; + \node[num_state] at (s_2.north west) {2}; + \node[num_state] at (s_3.north west) {3}; + \node[num_state] at (s_4.north west) {4}; + \node[num_state] at (s_5.north west) {5}; + \node[num_state] at (s_6.north west) {6}; + \node[num_state] at (s_7.north west) {7}; + \node[num_state] at (s_8.north west) {8}; + \node[num_state] at (s_9.north west) {9}; + + + \path[->] + (s_0) edge [left] node {$a$} (s_1) + edge [above] node {$S$} (s_3) + (s_1) edge [left] node {$a$} (s_2) + edge [above] node {$S$} (s_4) + (s_2) edge [loop below] node {$a$} () + edge [above] node {$S$} (s_5) + (s_4) edge [above] node {$b$} (s_6) + (s_5) edge [above] node {$b$} (s_7) + (s_6) edge [above] node {$S$} (s_8) + edge [above, bend right=20] node {$a$} (s_1) + (s_7) edge [above] node {$S$} (s_9) + edge [below, bend left=20] node {$a$} (s_2) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/GLR_example.tex b/tex/figures/GLR/GLR_example.tex new file mode 100644 index 0000000..64e9d1a --- /dev/null +++ b/tex/figures/GLR/GLR_example.tex @@ -0,0 +1,101 @@ +\begin{tikzpicture}[> = stealth,node distance=1.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] + \node[r_state] (s_0) + { + $ + \begin{aligned} + S' &\to \cdot S \$ \\ + S &\to \cdot a b C \\ + S &\to \cdot a B C + \end{aligned} + $ + }; + \node[r_state] (s_1) [below=2.5cm of s_0] + { + $ S' \to S \cdot \$ $ + }; + \node[r_state] (s_acc) [below=2cm of s_1] + { + $ S' \to S \$ \cdot $ + }; + \node[r_state] (s_2) [right=3cm of s_0] + { + $ + \begin{aligned} + S &\to a \cdot B C \\ + S &\to a \cdot b C \\ + B &\to \cdot b + \end{aligned} + $ + }; + + \node[r_state] (s_3) [right=3cm of s_2] + { + $ + \begin{aligned} + S &\to a b \cdot C \\ + B &\to b \cdot \\ + C &\to \cdot c + \end{aligned} + $ + }; + + \node[r_state] (s_5) [right=3cm of s_3] + { + $ + \begin{aligned} + S &\to a b C \cdot + \end{aligned} + $ + }; + + \node[r_state] (s_4) [below=2.5cm of s_2] + { + $ + \begin{aligned} + S &\to a B \cdot C \\ + C &\to \cdot c + \end{aligned} + $ + }; + + \node[r_state] (s_6) [right=3cm of s_4] + { + $ + \begin{aligned} + C &\to c \cdot + \end{aligned} + $ + }; + + \node[r_state] (s_7) [below=2cm of s_4] + { + $ + \begin{aligned} + S &\to a B C \cdot + \end{aligned} + $ + }; + + \node[num_state] at (s_0.north west) {0}; + \node[num_state] at (s_1.north west) {1}; + \node[num_state] at (s_2.north west) {2}; + \node[num_state] at (s_3.north west) {3}; + \node[num_state] at (s_4.north west) {4}; + \node[num_state] at (s_5.north west) {5}; + \node[num_state] at (s_6.north west) {6}; + \node[num_state] at (s_7.north west) {7}; + \node[num_state] at (s_acc.north west) {acc}; + + + \path[->] + (s_0) edge [above] node {$a$} (s_2) + edge [right] node {$S$} (s_1) + (s_1) edge [right] node {$\$$} (s_acc) + (s_2) edge [above] node {$b$} (s_3) + edge [right] node {$B$} (s_4) + (s_3) edge [above] node {$C$} (s_5) + edge [right] node {$c$} (s_6) + (s_4) edge [above] node {$c$} (s_6) + edge [right] node {$C$} (s_7) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LL_LR.tex b/tex/figures/GLR/LL_LR.tex new file mode 100644 index 0000000..3d3eaeb --- /dev/null +++ b/tex/figures/GLR/LL_LR.tex @@ -0,0 +1,21 @@ +\begin{tikzpicture} + \node at (0,0) (ll0) {LL(0)}; + \node at (0,3.5) (ll1) {LL(1)}; + \node at (0,4.5) (llk) {LL(k)}; + \node at (3,0) (lr0) {LR(0)}; + \node at (3,1.5) (slr) {SLR(1)}; + \node at (3,2.5) (lalr) {LALR(1)}; + \node at (3,3.5) (clr) {CLR(1)}; + \node at (3,4.5) (lrk) {LR(k)}; + + \node[r_state,violet,fit=(ll0)] (a) {}; + \node[draw=none,fit=(a)] (a1) {}; + \node[draw=none,fit=(a1)] (a2) {}; + \node[r_state,violet,fit=(ll0) (ll1) (a)] (b) {}; + \node[r_state,violet,fit=(ll0) (llk) (b)] (c) {}; + \node[r_state,fit=(a2) (lr0)] (d) {}; + \node[r_state,fit=(slr) (d)] (e) {}; + \node[r_state,fit=(lalr) (e)] (f) {}; + \node[r_state,fit=(lalr) (clr) (f) (b)] (g) {}; + \node[r_state,fit=(g) (lalr) (lrk) (c)] (h) {}; +\end{tikzpicture} diff --git a/tex/figures/GLR/LR0/complete.tex b/tex/figures/GLR/LR0/complete.tex new file mode 100644 index 0000000..ef2143e --- /dev/null +++ b/tex/figures/GLR/LR0/complete.tex @@ -0,0 +1,67 @@ +\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] + \node[r_state] (s_0) + { + $ + \begin{aligned} + S' &\to \cdot S \$ \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + \node[r_state] (s_1) [right=of s_0] + { + $ S' \to S \cdot \$ $ + }; + \node[r_state] (s_2) [right=of s_1] + { + $ S' \to S \$ \cdot $ + }; + \node[r_state] (s_3) [below=2.5cm of s_0] + { + $ + \begin{aligned} + S &\to a \cdot S b S \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + \node[r_state] (s_4) [right=of s_3] + { + $ S \to a S \cdot b S$ + }; + \node[r_state] (s_5) [right=of s_4] + { + $ + \begin{aligned} + S &\to a S b \cdot S \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + \node[r_state] (s_6) [right=of s_5] + { + $ S \to a S b S \cdot$ + }; + + \node[num_state] at (s_0.north west) {0}; + \node[num_state] at (s_1.north west) {1}; + \node[num_state] at (s_2.north west) {2}; + \node[num_state] at (s_3.north west) {3}; + \node[num_state] at (s_4.north west) {4}; + \node[num_state] at (s_5.north west) {5}; + \node[num_state] at (s_6.north west) {6}; + + \path[->] + (s_0) edge [left] node {$a$} (s_3) + edge [above] node {$S$} (s_1) + (s_1) edge [above] node {$\$$} (s_2) + (s_3) edge [above] node {$S$} (s_4) + edge [loop below] node {$a$} () + (s_4) edge [above] node {$b$} (s_5) + (s_5) edge [above] node {$S$} (s_6) + edge [above, bend right=20] node {$a$} (s_3) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state0.tex b/tex/figures/GLR/LR0/state0.tex new file mode 100644 index 0000000..b0b662f --- /dev/null +++ b/tex/figures/GLR/LR0/state0.tex @@ -0,0 +1,14 @@ +\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] + \node[r_state] (s_0) + { + $ + \begin{aligned} + S' &\to \cdot S \$ \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + + \node[num_state] at (s_0.north west) {0}; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state1.tex b/tex/figures/GLR/LR0/state1.tex new file mode 100644 index 0000000..06edbd2 --- /dev/null +++ b/tex/figures/GLR/LR0/state1.tex @@ -0,0 +1,23 @@ +\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] + \node[r_state] (s_0) + { + $ + \begin{aligned} + S' &\to \cdot S \$ \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + \node[r_state] (s_1) [right=of s_0] + { + $ S' \to S \cdot \$ $ + }; + + \node[num_state] at (s_0.north west) {0}; + \node[num_state] at (s_1.north west) {1}; + + \path[->] + (s_0) edge [above] node {$S$} (s_1) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state2.tex b/tex/figures/GLR/LR0/state2.tex new file mode 100644 index 0000000..aefec37 --- /dev/null +++ b/tex/figures/GLR/LR0/state2.tex @@ -0,0 +1,29 @@ +\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] + \node[r_state] (s_0) + { + $ + \begin{aligned} + S' &\to \cdot S \$ \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + \node[r_state] (s_1) [right=of s_0] + { + $ S' \to S \cdot \$ $ + }; + \node[r_state] (s_2) [right=of s_1] + { + $ S' \to S \$ \cdot $ + }; + + \node[num_state] at (s_0.north west) {0}; + \node[num_state] at (s_1.north west) {1}; + \node[num_state] at (s_2.north west) {2}; + + \path[->] + (s_0) edge [above] node {$S$} (s_1) + (s_1) edge [above] node {$\$$} (s_2) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state3.tex b/tex/figures/GLR/LR0/state3.tex new file mode 100644 index 0000000..74b9fe1 --- /dev/null +++ b/tex/figures/GLR/LR0/state3.tex @@ -0,0 +1,42 @@ +\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] + \node[r_state] (s_0) + { + $ + \begin{aligned} + S' &\to \cdot S \$ \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + \node[r_state] (s_1) [right=of s_0] + { + $ S' \to S \cdot \$ $ + }; + \node[r_state] (s_2) [right=of s_1] + { + $ S' \to S \$ \cdot $ + }; + \node[r_state] (s_3) [below=2.5cm of s_0] + { + $ + \begin{aligned} + S &\to a \cdot S b S \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + + \node[num_state] at (s_0.north west) {0}; + \node[num_state] at (s_1.north west) {1}; + \node[num_state] at (s_2.north west) {2}; + \node[num_state] at (s_3.north west) {3}; + + \path[->] + (s_0) edge [left] node {$a$} (s_3) + edge [above] node {$S$} (s_1) + (s_1) edge [above] node {$\$$} (s_2) + (s_3) edge [loop below] node {$a$} () + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state4.tex b/tex/figures/GLR/LR0/state4.tex new file mode 100644 index 0000000..79227e8 --- /dev/null +++ b/tex/figures/GLR/LR0/state4.tex @@ -0,0 +1,48 @@ +\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] + \node[r_state] (s_0) + { + $ + \begin{aligned} + S' &\to \cdot S \$ \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + \node[r_state] (s_1) [right=of s_0] + { + $ S' \to S \cdot \$ $ + }; + \node[r_state] (s_2) [right=of s_1] + { + $ S' \to S \$ \cdot $ + }; + \node[r_state] (s_3) [below=2.5cm of s_0] + { + $ + \begin{aligned} + S &\to a \cdot S b S \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + \node[r_state] (s_4) [right=of s_3] + { + $ S \to a S \cdot b S$ + }; + + \node[num_state] at (s_0.north west) {0}; + \node[num_state] at (s_1.north west) {1}; + \node[num_state] at (s_2.north west) {2}; + \node[num_state] at (s_3.north west) {3}; + \node[num_state] at (s_4.north west) {4}; + + \path[->] + (s_0) edge [left] node {$a$} (s_3) + edge [above] node {$S$} (s_1) + (s_1) edge [above] node {$\$$} (s_2) + (s_3) edge [above] node {$S$} (s_4) + edge [loop below] node {$a$} () + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/GLR/LR0/state5.tex b/tex/figures/GLR/LR0/state5.tex new file mode 100644 index 0000000..6545b4e --- /dev/null +++ b/tex/figures/GLR/LR0/state5.tex @@ -0,0 +1,62 @@ +\begin{tikzpicture}[> = stealth,node distance=3.25cm, on grid, scale=0.8, every node/.style={scale=0.8}] + + \node[r_state] (s_0) + { + $ + \begin{aligned} + S' &\to \cdot S \$ \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + \node[r_state] (s_1) [right=of s_0] + { + $ S' \to S \cdot \$ $ + }; + \node[r_state] (s_2) [right=of s_1] + { + $ S' \to S \$ \cdot $ + }; + \node[r_state] (s_3) [below=2.5cm of s_0] + { + $ + \begin{aligned} + S &\to a \cdot S b S \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + \node[r_state] (s_4) [right=of s_3] + { + $ S \to a S \cdot b S$ + }; + \node[r_state] (s_5) [right=of s_4] + { + $ + \begin{aligned} + S &\to a S b \cdot S \\ + S &\to \cdot a S b S \\ + S &\to \cdot + \end{aligned} + $ + }; + + \node[num_state] at (s_0.north west) {0}; + \node[num_state] at (s_1.north west) {1}; + \node[num_state] at (s_2.north west) {2}; + \node[num_state] at (s_3.north west) {3}; + \node[num_state] at (s_4.north west) {4}; + \node[num_state] at (s_5.north west) {5}; + + \path[->] + (s_0) edge [left] node {$a$} (s_3) + edge [above] node {$S$} (s_1) + (s_1) edge [above] node {$\$$} (s_2) + (s_3) edge [above] node {$S$} (s_4) + edge [loop below] node {$a$} () + (s_4) edge [above] node {$b$} (s_5) + (s_5) edge [above, bend right=20] node {$a$} (s_3) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/cyk/graph1.tex b/tex/figures/cyk/graph1.tex new file mode 100644 index 0000000..407d0ca --- /dev/null +++ b/tex/figures/cyk/graph1.tex @@ -0,0 +1,19 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge[left] node {$\{A\}$} (q_1) + (q_1) edge[above] node[yshift=5pt] {$\{A\}$} (q_2) + (q_2) edge[below] node[yshift=-5pt] {$\{A\}$} (q_0) + (q_2) edge[bend left, above] node {$\{B\}$} (q_3) + (q_3) edge[bend left, below] node {$\{B\}$} (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/flpq/path1.tex b/tex/figures/flpq/path1.tex new file mode 100644 index 0000000..14d88f8 --- /dev/null +++ b/tex/figures/flpq/path1.tex @@ -0,0 +1,8 @@ +\begin{tikzpicture}[node distance=2cm, shorten >=1pt,on grid,auto] + \node[state] (q_1) {$1$}; + \node[state] (q_2) [right=of q_1] {$2$}; + \node[state] (q_3) [right=of q_2] {$3$}; + \path[->] + (q_1) edge node {a} (q_2) + (q_2) edge node {b} (q_3); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/flpq/path2.tex b/tex/figures/flpq/path2.tex new file mode 100644 index 0000000..62a7a83 --- /dev/null +++ b/tex/figures/flpq/path2.tex @@ -0,0 +1,12 @@ +\begin{tikzpicture}[node distance=2cm,shorten >=1pt,on grid,auto] + \node[state] (q_0) {$0$}; + \node[state] (q_1) [right=of q_0] {$1$}; + \node[state] (q_2) [right=of q_1] {$2$}; + \node[state] (q_3) [right=of q_2] {$3$}; + \node[state] (q_4) [right=of q_3] {$2$}; + \path[->] + (q_0) edge node {a} (q_1) + (q_1) edge node {a} (q_2) + (q_2) edge node {b} (q_3) + (q_3) edge node {b} (q_4); + \end{tikzpicture} diff --git a/tex/figures/gll/complete.tex b/tex/figures/gll/complete.tex new file mode 100644 index 0000000..d2332a6 --- /dev/null +++ b/tex/figures/gll/complete.tex @@ -0,0 +1,26 @@ +\begin{tikzpicture}[] + \node[state] (q_0) {S, 0}; + \node[state] (q_1) [right=of q_0] {S, 1}; + \node[state] (q_2) [left=of q_0] {S, 2}; + + + \path[->] + (q_0) edge[loop above] node {$S \to S \cdot S S$} + node[below] {1} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {2} () + (q_1) edge[loop above] node {$S \to S \cdot S S$} + node[below] {5} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {6} () + edge[bend left] node[below] {$S \to S S \cdot$} + node[above] {4} (q_0) + edge[bend right] node[above] {$S \to S S \cdot S$} + node[below] {3} (q_0) + (q_2) edge[loop above] node {$S \to S \cdot S S$} + node[below] {8} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {9} () + edge[] node[above] {$S \to S S S \cdot$} node[below] {7} (q_0) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state0.tex b/tex/figures/gll/state0.tex new file mode 100644 index 0000000..426d077 --- /dev/null +++ b/tex/figures/gll/state0.tex @@ -0,0 +1,3 @@ +\begin{tikzpicture}[] + \node[state] (q_0) {S, 0}; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state1.tex b/tex/figures/gll/state1.tex new file mode 100644 index 0000000..4481647 --- /dev/null +++ b/tex/figures/gll/state1.tex @@ -0,0 +1,8 @@ +\begin{tikzpicture}[] + \node[state] (q_0) {S, 0}; + + \path[->] + (q_0) edge[loop above] node {$S \to S \cdot S S$} + node[below] {1} () + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state2.tex b/tex/figures/gll/state2.tex new file mode 100644 index 0000000..28b9e57 --- /dev/null +++ b/tex/figures/gll/state2.tex @@ -0,0 +1,10 @@ +\begin{tikzpicture}[] + \node[state] (q_0) {S, 0}; + + \path[->] + (q_0) edge[loop above] node {$S \to S \cdot S S$} + node[below] {1} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {2} () + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state3.tex b/tex/figures/gll/state3.tex new file mode 100644 index 0000000..22fac6a --- /dev/null +++ b/tex/figures/gll/state3.tex @@ -0,0 +1,13 @@ +\begin{tikzpicture}[] + \node[state] (q_0) {S, 0}; + \node[state] (q_1) [right=of q_0] {S, 1}; + + \path[->] + (q_0) edge[loop above] node {$S \to S \cdot S S$} + node[below] {1} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {2} () + (q_1) edge[bend right] node[above] {$S \to S S \cdot S$} + node[below] {3} (q_0) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state4.tex b/tex/figures/gll/state4.tex new file mode 100644 index 0000000..58ba3a4 --- /dev/null +++ b/tex/figures/gll/state4.tex @@ -0,0 +1,15 @@ +\begin{tikzpicture}[] + \node[state] (q_0) {S, 0}; + \node[state] (q_1) [right=of q_0] {S, 1}; + + \path[->] + (q_0) edge[loop above] node {$S \to S \cdot S S$} + node[below] {1} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {2} () + (q_1) edge[bend left] node[below] {$S \to S S \cdot$} + node[above] {4} (q_0) + edge[bend right] node[above] {$S \to S S \cdot S$} + node[below] {3} (q_0) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state5.tex b/tex/figures/gll/state5.tex new file mode 100644 index 0000000..e8e80aa --- /dev/null +++ b/tex/figures/gll/state5.tex @@ -0,0 +1,17 @@ +\begin{tikzpicture}[] + \node[state] (q_0) {S, 0}; + \node[state] (q_1) [right=of q_0] {S, 1}; + + \path[->] + (q_0) edge[loop above] node {$S \to S \cdot S S$} + node[below] {1} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {2} () + (q_1) edge[loop above] node {$S \to S \cdot S S$} + node[below] {5} () + edge[bend left] node[below] {$S \to S S \cdot$} + node[above] {4} (q_0) + edge[bend right] node[above] {$S \to S S \cdot S$} + node[below] {3} (q_0) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state6.tex b/tex/figures/gll/state6.tex new file mode 100644 index 0000000..69d88b8 --- /dev/null +++ b/tex/figures/gll/state6.tex @@ -0,0 +1,19 @@ +\begin{tikzpicture}[] + \node[state] (q_0) {S, 0}; + \node[state] (q_1) [right=of q_0] {S, 1}; + + \path[->] + (q_0) edge[loop above] node {$S \to S \cdot S S$} + node[below] {1} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {2} () + (q_1) edge[loop above] node {$S \to S \cdot S S$} + node[below] {5} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {6} () + edge[bend left] node[below] {$S \to S S \cdot$} + node[above] {4} (q_0) + edge[bend right] node[above] {$S \to S S \cdot S$} + node[below] {3} (q_0) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state7.tex b/tex/figures/gll/state7.tex new file mode 100644 index 0000000..1e57543 --- /dev/null +++ b/tex/figures/gll/state7.tex @@ -0,0 +1,22 @@ +\begin{tikzpicture}[] + \node[state] (q_0) {S, 0}; + \node[state] (q_1) [right=of q_0] {S, 1}; + \node[state] (q_2) [left=of q_0] {S, 2}; + + + \path[->] + (q_0) edge[loop above] node {$S \to S \cdot S S$} + node[below] {1} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {2} () + (q_1) edge[loop above] node {$S \to S \cdot S S$} + node[below] {5} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {6} () + edge[bend left] node[below] {$S \to S S \cdot$} + node[above] {4} (q_0) + edge[bend right] node[above] {$S \to S S \cdot S$} + node[below] {3} (q_0) + (q_2) edge[] node[above] {$S \to S S S \cdot$} node[below] {7} (q_0) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/gll/state8.tex b/tex/figures/gll/state8.tex new file mode 100644 index 0000000..f377e2c --- /dev/null +++ b/tex/figures/gll/state8.tex @@ -0,0 +1,24 @@ +\begin{tikzpicture}[] + \node[state] (q_0) {S, 0}; + \node[state] (q_1) [right=of q_0] {S, 1}; + \node[state] (q_2) [left=of q_0] {S, 2}; + + + \path[->] + (q_0) edge[loop above] node {$S \to S \cdot S S$} + node[below] {1} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {2} () + (q_1) edge[loop above] node {$S \to S \cdot S S$} + node[below] {5} () + edge[loop below] node {$S \to S \cdot S$} + node[above] {6} () + edge[bend left] node[below] {$S \to S S \cdot$} + node[above] {4} (q_0) + edge[bend right] node[above] {$S \to S S \cdot S$} + node[below] {3} (q_0) + (q_2) edge[loop above] node {$S \to S \cdot S S$} + node[below] {8} () + edge[] node[above] {$S \to S S S \cdot$} node[below] {7} (q_0) + ; +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/mcfg/mcfg.pdf b/tex/figures/mcfg/mcfg.pdf new file mode 100644 index 0000000000000000000000000000000000000000..dd7aa00c514b7f57bfbf3bc1592652927bb45285 GIT binary patch literal 6679 zcma)>2RvK-zsHRZMHN+aAU0JbA~C8~?7h`)5Tr&(Vm(^BwQ6r3RI6IERw=c`ELBxS zYt>e(c2L|z>$!dYz4vwR$vF9be&@Ho3B|(r7gp&K!a`8T;C;$jRS>L6U zk^%^8AYAOR4gd&2(xU_b0K!U0CoBR@I6J|y2nB=<$`(N>Elr8Rq7iUsO0U124K=l| zf@tgZjqxcjJ~vH8m)>{Mm6LaUJbKmj#iPgh3FOP!ehoIOkN8!CJ7()LqIYV`FIGey zF-~8IX4S(54^#$ugIz}UJe-An#rOBx0S0X4(c8k~HD8acX1{hyx^53YF8AE-nN%5; zu0C_-Y^Qw$KPxc%I4dfIruX3+VVr{pI^J>j3;o1p z);<=YzI@*)I4HYfdF#uk8_?)Jb(n`ANp;Ee)*T^B#;VOAQ>*TlmGy5PM-^i!52~JV zKB-50HQ{suEwUu;jLwzq*S43vVGW=t-W%b4z$@)@-7LjwMd;7;V=ucPo zw64f~wV_27sJLOd(4oE&lJ_31H!kbVpU=b7Kl?Pb^8Fm!&RdIU1177%o$-h9VHBxn zqthiO!|!>7^KWlWds7H(=grSqwNY9A2<}O0Ty-&O{@$z3{n3fkY=I}nlddK|jJ_;! zRJOm^RFg|}Qn~3qNtEDbyC3S1^wX4sEG5Fl_E#Dceh~|RnDxXnA@9Y2Kw>-50{>GU z#|5G2g;mza5{dyJB}EhnhcFySFaW|ZIRFSCYy&5J6H0{8@bg<(3FU(Q?P@zgpdb(c zJt;B5MTGaS$wdB{3?OXa?TP>h>%i?10B!*2cyb*$8bKHfbkbK?6Jd*l%cHyiW&{Zc z0E>ZyprSws7z_{ri3mYNK@gAxz~Z~!M8I5vx{cUAGXFOI7GM$^Us?T2mk?#1OIgsnlbkAGEhvCan~NGJ5cc)U%~PQW8-MDgF*vh zXyt*{SLIlBnKW(bAyO4#9UZjiR%yxQSUH$!`^l831F0`E_?Vmt60Z;C;3!VRT~@ZE zJNLvf;!#Ajb9`6k7rFLfRNHEL!|WGSLCxML3B#R_-aoz>Sll7G6ENdH@doqmQNGN! zwC}0L9~A!R#SE&s{fU(XGLps9Bs>BID`}Y3&QX}7*I|yD{c-+ zfEkU~Ot&nbB-1Syq=}V(Q(Nx+=pG{lqGEWFz;4O!5nFj>^8#*dRqh}&RUxApe%nmh zR(zf%HcG{#7CgG3?U`$go-b~jUMUyJ8E)9Wn<>f6Y_O9_7lb>l5*QnBSjn<|KS_!A z3+cX>%_Ps<-l1vS`LfZ!{OWGT*-$LiFjq78_4;9?_x(8~1Wn+Vy1@wud}AK$uXi2y zq7Rfg#Tvz3sdg!iLMn3E0TvmB4 z8Kbq1K96i4Gw>b1rHNI#Y39GBq}pcB1q)Ioee;=@OZNKdVAa+6Zz~)iCQgarLUAX4 z!F`q#fGkyd#|ZQ{j&Boak&e#{?%PSf``omK+iH3t{;`n{aDM~$iY_V zQ?m~RxZu)0=~E=XJX1`{OD^wzpSm=!9Jls@Mb0dUB_YS@Tx7@eteRus2>c!WcA9ple3x{D+ zuIZei%BK7jWMadks0h}+quRw_l&cZ-l;V2Cusq`OyQzqZ)?A2FQJIuWMA;>nR4Li@ z?i(31Wz-t&)HA2OE!Wg#i+B4wSmXqo{S8(`xy(~3tEXs{%V$i3*WpeF9fuOL>&F1aK$2o_cL%r%>NjR@5?$OL~R@&|G(DX29L^R(R zQ(zfjsCy&6#4kw0n=oc{%_Dit$b%vVsHe5RJ(HXv#HkQ_ttBQaIP^hX4Y>62Jrb(v zk>=;2{Gave4Q^;y#^<Cx0aX2+KyJW6;GG+XIVYX;%bLJ zd?*WbzH)1>FDyb{aj+gDHP>&9^2@)j=*wCz)1k%h-lf(Bdl&RR$2IVU?|RYgy-w)1 zt&Zx7L_y(*JMuz4GI&nhiyugqk*2Euw+86)1%qxzaKLA4p)v=`G}=sv$+@~y7I59V zdygJ?)c1s9aKj;AD^+N=d^dHdYwmyN9x@s}Kcpo`US`)isXJm?%dOw}@t$dJtNrEd z8Iu*GB!0+e`nTw3mIYN#2K3_P)>7(i)E=j4L@exBn<(AF^G2llMZeU(ufWv?IyWk9 zGuL#ct}UFh`~2!gkZv>Fq%diqv~bXN)Xij&NAis(-U1t{vUrB3uOB1>*~eX z)E*a$RrC54d_3s(&9j zkrz-$-h*9XzQXIpM*^Zc%#U9TJHOsEWm)XE-3r@a6kU=QMfE)#4WY4Mu`I(1OP4r( z9c0@XDRvs~+ng-Ugmi85viTtGd#^~}AGh#i4iOxtO|s&LlZ@7cyDG`6;CF#d`7IpGc=i_7tKdJhd#nw=vs$%Fl0`1%KN2U;h!3AX*qh=Ngy_LGm$N2vLam25Md4eM9wz zDiWL@l<7R&?Y)3|Jo0cqp)hm%)~#i=q={S0f=bU7J2_H=C4B{!A$o!n{LOa7q7j#_ zh^A{I^O@Kq`;e}xK6Val$i*o0uA3~SwXoD#e{vS{ybf*8a4EkfsRXCEkuJOXP9FEw zyI%(`n({L9KK)v5F0OMk&Yp#;XVSw;^H613YX z4M`kKjIYJxM--lbVY0RIbX|Df>AI0s>Sm}<@lrfn&Kccs z;>I>JPIsLedMDXgJoWv2Ax`gERAXX+LENFT>Zfym`CT=@&}MX#>0OqW`jGjlhI2bB z(Bui&Ncg=_L4e-Sv&wuI!5|}$RAo8~oX#CA3cEQLwKEywbg6g32Y+m!xkM;(5=s1f+M}LnS=7w^(aX$tvD$21+=YO*$?wXP7IA z6|I+if7pkj#Q3!>G>CagE{0EbBI;dxUzaB5M5Rk7d2u5?LinsN`i%??rIb3{#xIDu z{Wat{cVk@gzD3)-`(AgS$^BvZ)Xz2Zi?QX;B`6ynR@58xA2vmfAAbL_eXz2)JTn{r zJ~?D>o$A05V@vsrYj=6SFMVky8Slq0$zGusOmX4M1hbXwvIffF2B}5QgS)X5>@(D- z1~9IV_B21c$=|&aJU|}2uOO~@V39oi=$VpZxzpW^JongUHoBEhdK}=-q-s9!nj>fS zNSEhI<83@_uOi!a&>8|P>TrtgC-?5&+jW8zPOx$ZWY!v*u+AS?T7Qf@T5exOfB!=3 zYt#Oc+cE)f<@=*6%8%yjX&K+@l`Ct{a2xDDID%vOd|6wM67a(gKPo7CRex}u?e$0u zEoWbP5@x~eH9G~L)L@WdefXT)mut;{<}l>y5kqr4y$tp%o8wwg3;t}_YX9brV`;ff z?R;Tt)Y{OYWtl@V-cqDqV2vg0NNCMDj8`82Y0Y3Q2{)C8x1(W=$M0Q#?ll_mlKW0N zj+5Rh5g(3A=C0>jQw(c}#|PqC=(9X0vj=?LRIC>U zlP+P})vn374DHXY@2=hZ5Op(fNJBpjh7ZOqN4JM9)3Zgl@l(jALt#=E|w@)YF zJn3N!o0y9E(S%N^U(#J45cR8UKyFg9zo>HH8V|@+YPm9ttPwvdVZU~ zbSzAOODOp^FX+9Gm2=T+ZEI&iAu4OlJmrsgw>%s-J<}IA-D^S>6J%iOdNMYd3eRjJk* zT6?D|CMcJ72R5jv&^L56@zbNS6H)xldKZ#_773dz>7!o#IbLq@xK5)VOkrYUk0Y*f zk3F8+qK`o4+@8z{t4U#qzNqhH{Uqw5lep!iJNq@J=2H5X&lbPD(!C-1Xpq51c5;Be z-F$}LX2i=d8)iP!+$`Yy1o(cjQNUT;)H(pCyXykF9=^-z9=qBW>um(mYnKv;QfW26 zI!j#@el4t}DCJi7^)hGi?r>OnxAluC6T4cDvmxdyOt3(&-8;#zN1}r)yoLb{ua~Y| zn{L-=Ftn9?k7^B|2XoQ5-jN(mU6Hq{qkivIoez9&yjo`mJ5 za@}X2fXzD&YKXgU&=&QDbjX!V&4|0gd@T83XYt z_ZMRTi-9Fhp8F;Kd>#f7AL##o5Y8gD$E5{8-M%XIAbK>r%f86~ItI3dendES-DzZsSXj$E{B4oNnunczLDYWZr&B)&h%&s4lY$f;v4-ObS zC3cLs5=NX0+N&W`9N(_QX`_qBoJ)L+-ui2kk;HjEe~$z=t?Yj&{Ww~9&~!O6#6a{s z-?fFB!Lj-+usnVIP7z1L_Ls~LhaC0Lh?sUvn|548^T0N}1&W8kJq@Z8ZNvHgg<5#cBxFg9qUD;9+&B93FKqXl;+AR3sV zg0Z2RfCAz!+{j&@089R9SAshuoxA~jKbru=HvXTDPH=ky6%qO8O8K7TxD(Pw&c)sd0RSHNlf&2$X^@17__0Y`AJG;R0Yi=j7~E9_ zfwXrZ03*UM$C5r4;cNsT;1l8wh=$6ELEIq$ydXpXL^ks~t09uAKfUpD1b1ufF{Lsf z&>*6xj#YU$264>1{x{Dc(HJbu0ggU#fCl`R4FXCWkMM7I1C9govlJ9v2nZVKVh<2D zM!LwkV2~%maX(|EE!F|^3x*Nv=i~*JAiy!g2M7=c6ZZ#(p0q&0P{7IOMEmm$6(>?N zs06WmfdGgY1Ry3xRDQl75HWx_A!H{u@eDmquHTja`?myP%wt$bfNm&57bKCk1BkbV z-^1}|auN~Y&zw_7+7fq9T#4R4*w39v41Z&9px+^*4jN_aZbKmad^T_-8U+9efgnPJ zrSmypv96NB1e!@u?a^>o2c!)~2!*!i|Czur0{_P%Q7#HZ63V9_DMH9wAVdTT5&?+< zfdW7sl>Kqwj<@iOYyLM4^+F@;D1iWwC?)Wp0|13Uzz~2P z;FkskiV=cBJOC~y8c;%nFx`J>;vho6{zC(T2+a3CG%*Q+fBvmOpkjn5{96NoAb<1~ zl@R}9Ef63vd;i^+05JdP3lRnW(H9C5{bL_c5n}3|jE6aB)7YYV}DY>~7wUsFU3+#SSo&W#< literal 0 HcmV?d00001 diff --git a/tex/figures/mcfg/mcfg.svg b/tex/figures/mcfg/mcfg.svg new file mode 100644 index 0000000..8cd991c --- /dev/null +++ b/tex/figures/mcfg/mcfg.svg @@ -0,0 +1,164 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + CFL + TAG + 2-MCFL + 3-MCFL + m-MCFL + (m+1)-MCFL + + + diff --git a/tex/figures/mcfg/mcfg_2.pdf b/tex/figures/mcfg/mcfg_2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bc1933f653d4a2681d6d373476d7442cdf05d5b6 GIT binary patch literal 6053 zcmbVQ2{@GN+dobYH7S)POBl(%%w`6WC5%1$nx!$u7-2L^_9cuKTe4&=SrS=8LQ#@! zEZLQiB4jB_vzyz2N-oQ4m?QgqCl&ojh*9>Rt5f!A4*cIX00VVOO5e$06!i~(e4p!*`?7t>i}iii%Pb*Qxy3)r z;|uB<)g-1A7%0KYobvUN51NuVwAmxD8K z-34D4?}${eO6&ewH;C=y_7v&=0*+vwYa=slo$#wNXKSKVe{H&?>A={R&$LsLD za>d1osPTl*3?v$5-Eabh)L&~AFw&jXX?B7g@$0}o-ROW+b3^j2>Q8Z%cs&rhDRjf7 zIGhXorDdL}s4R$;#pl_UNl@zZe$&+Y#%k~LAuiH7;ERvSxw{aboKFdUVVrAE8nntn z)e!cjk`G=}6b0*^D+_!+k`Wz@G*cYO;j)4pcCO6yoqzZKW*=3CEJr;LYG2y2kU#UX zDKzWdC_lF&GWxRgoG!cB5Zm1`Ptt&)Umbo~L8+?d;rRBap4-FrMYW?2UEe&`Jxd0z zN#ELve}PE&TgG~3TvKA*ELDrsbtuZ_)Z1D&6T`TK2&Tu=DE*Wr#e!T`^^o*}1Fwav z;0m{mOW&d$hOj!DPn`tJhkb^3>)`W(q z=SjzwP9C_Y7N*)9s(Nh@c|IioT(%wMTB2m@5X@58a6OtveTMWq94rF8Zvu3JC zb8r~3%ypbQW@&NxC`E1HJ=jB|(m;Y(t>)!imp-iWDdyYSP=3*Q^0~eSh9ZiQ;sYsJ1P zLIXtG2nqLlZkoFDskgl8@9K}`7}xdk>9LzmI88Pe%A3sxa7E+mY@B#hL!u$I?9alt zUYj|n#0_;zrs#_!-Fmm;Wo1RvwLN)0-aw=plr3*N;XGL-tZ6*sR{Zs&KowrlX2{m^Q6 zw4B4deX*em82gEB?oi|V}f2i93wIFF_kW`o08(@CEhs)kC zab3jxu_^nrX)1*Z=1tLa`Q*vm?pU$^cAu;GBOac%jDdCp4x-N1?W)_aWgVwe3G)r- z7r4S7-u^&O!~l}ER6Qm;>apbOb2rrdu%Lv097-cKOF9K^vCIYO542GcYM;Uylzrmy z>2E3*E$2Z~$Q2gYUTe9Fm#Rwyk*5UJSz9QB9TsR8vQ`$2a&E z&5Shlt2MLB_GyNDV$wL0Gc5{^CFl0#b5_j6yDdP+hhD2DztucVkC;r@OREOcR@uxkg4k7j38Krsg~YeU_;O>Rmc{Iy?*L zxeKweNEy)_EGspJ{8hD~WjkSD##ejz$T>CgfW)NT_flVjLiX8)Z1TWF+Zrw=->dKH zOo;D#7p`!;@%pf1bdu!dn4BTMOzh$vE0^F-_qX{M&rgeggO{;04UYGhoN><`96d^W zbQn1_SUMI!rkroI*8jVxTel{3fx0FFFUnK=?w7o5b^lZ`NaCc?sjOfUn;zOzy@=$r zDP@h!E9H4ePM??v%SjJ#_|jB_dvvCEqyZW-BU#w^QABa#OQu0*58~=D@QDFCnk)}W zWJI^#KOuavvt?{T_{CInlK)F;v6I&mq^EaDrWC5%@yz^2WT1_Gk)p#xYs*S!cl8Ui z#3B9p(Feu@MR~E7bw{wuwWrRJOO!{110;sp9Q{i*U0zo(ZN{q|;w0vabH_`#bvzzQ z(XcXY$}0lLN6&RELMFwe7K9FK3fT-uEcMtyJ9%GZYn1w`wFNq`d%+RYed8%jlrBm@ zZ}SGH#$wJ^W)xUi{bqY%Q_}U%9GAD5qm$C)y$ZBo(D15dLIpCs1pd0@ayw64jXH<@ zmKBHpCG)h}%LY&RVtFr|cy$8XQcfLE5riCgcFWF0^me>&EHP$Q!7mgWaqbY0LSagY zNRuK;_tNDAMl@A7r_|+bf;)n~6;yMMg)-WpB zhKX@e30t~VvbcbddvSL%L}zrMJ`icRv`)b}n>1Uk*<&-uW^c{hTJNeobzDFYR3nP# znus~(6YKBvkwT2+pM`LX9OEsote!9COeHugEw)zU3aOTl4L0??8JYfm5t{{oU)i&XK^6ljh^29!+&16d5ZE_lCaee8lRW=cZf+x55-yM4M zDp}}6SUO+sTiXAa0`(k74Z2=5l66pE;*~dhZnQx8azd8Y!RW#$?zBjC4@)ZVFtfsU z^Nw54%!NNknFUHi-Q&lIv6^$TzzVDM4~6%wi1EvgmMBYEs<~6MDR*;bfKiu@-K;?t$mv21NH;4KO z5_!r)%M%m9lYCwEO`td*ziFn5rPkHn5Rr5Z$OQQIR7mdw)A%mIM95k1hW#%auz?|g z+IJtw%?_+A#}`}9POeV-Ry4oRBRqOXb!R+x(W92vB+uG5)Ae+CXKX0jmdmi(ZBKp! zQbI)-I-4?+7wbC68DpjTu$;&JByl8R5~n!umr~H3tn!3HMUj3Z#WSpSyjnFHisP>L zQp=ezZzVeRDcA@PeV3u0?p(m`tv~+Rt9(7KFDx=<0P_ z;^Hn4o-2L!fv*eYo5=HkBj$pj^0AAnECF|wqi66wfAr+t!Qffz(E03=Tz*gb!*VWC zSEe(sD-Y!I!mQV(!6*BDv{Rd}NlY_VVnjsIJmUS1`_A*+F}SykEL9F0#U4OPXNlMZ zE2T7L@tjs=7H4C~$Lbt?df(qCZuDKAgLB)eW8CGq4z%o{4Bc;fYj7Vif7l6#zR9Ga z1W)`Y7T1x_+ZhWl#BmD=x!A*7hE6Fx+6PT=uWL^hR^{fB0NCZF4E@9P7Z1;jL{fuX zmk6ISZgq>}Ud%(X@Opf(0NG^`gE3T+BVxHJGP;eDz?5@4Xgrs>$GP2LXzE>(aY>g# z4RE=?rJvtjrdD3m$A&aE5bqk@;5kb#ZAws@@6~Ps zS2D7`vJx5!9Vhn}%GyjNt%+|M3``ZUc)GdemTet79bpD&^{#FU5L#zo?}7B(^Sl!i z-&GJyzHW<zoH=x0@45Y9{ z&Hdl=7kwC%CF|joQK#{l1f3<?OyvchS0#=trJdEo zKfN1O2Eg`Le@u2ti+(9i@nRpb@YWm4u1^Kv#l9BSAE1l_nr!8(J0xQyWCavtQaPee z6y4N{9&dL2wg`H*J_onbwe+6EULP=8$lYRG*=N=S05VFM%079ZBqZzAu zV)%yA30i+XR{R{o(JAS6aBu=a3FbS$nN!H1v|gaD?8SVC{2nXl_Qv1V!+6lvK~PSh z=~JKYH<-P(!xi7V+mXjp+3##mU)U_KH)KW&y?p1*iul?fBImuxw!Lzp(O0FvG`HWU zw4Wj%S&&C;fdj}gN;xGqsDzN>$(FY^o7rdGrSB|e-IucH_bxR-QR)fIiJGW94n20x zt44hFnMXLojdDs<$BNnc4VxS!+K3!2K5>gl_3v!jP?;vE#~}`=#Cm-S_g_i;^;yOb zjJ&N-`DZuTA4;*JZg8mF(7UP9+UP{NYPGDcDHieS)L49+FDjFnm9wdtnM2oo;~?b# ztNa8bg*oks!@V%9F8hrpMa(6Z#@xXPZ_&m#5R0+eKN=aqHe>eNPpjm@GRL3fGAdJQ zIFQ2=iCIcd9)fK~CXi#=HBu|98t81kzW_q);gfzJ7mqAmRlw9Tzg%)7B(eD*KCU67 z`QE6zL(iig9I{q-gHodf5iA|$%`eV5*?`4(_bsfnUI~1s@LYOf#W9%IYh}Gvab7J5 zwB_Ue$U*igV#U1KXo@Y0)R;VvOcBTvTyft2?3;F}Q1Y3if}8AT9giMM(l(l!&{Fb~ zuosMWxS^+75TYfBe9?aJ9YCgWMk1t)vnx=Zea`q&chQko53@d8FfBQaG6pY0%RfliP@4S-EY<}=c z7!(5E<9Z6eb07$v#Qopo5xZEb$4lT5&2|4*QazesQCUi-s3r*>Pp8z$Ul_O=51T|C zZ9Morfcct9-odu94%>@Q7B7D3wqXkn+OQ^bT>xA7*?#Ji4CB{ATZ^mma?Izhn8%SK zWdU6*~2R} zmeV62!=A_ajJoEhmi*naHt@MZfiboN!>`lMb6k|e7pLV!HkLJFRe$+wbS`MpWO)vTOd${@S*fqLTtJ0ilO&626^p{6vac8_Ht?TegH}PR@pG#BZ`& zuTyax2D;08=`>vfLqrpBo+LbhPGfhN`#F?5jfU%MTbWv_OKM55BAU+l6`=AvCVhT%TN(<3?>N*^p4u23)`cbt(7M@inUXN>7C>64^a$vN z_MSnHkVdXCP#~Ru|H{YdYQ*o^*zJMrNZL^%%xH|Co~a%0Srieoqig)P%-{$_lDZ3u zu$KUR)DIg1k=^OxpXmnfEXXeOH9crzAkG5|1XT=LKxhvbC=a8@2SeP6BT#haU?cH#=98jLNSbO&W@2wz5 z*IjmRSz53=q6|%3!JB*F=-MZcejNO|B)Y%Lqi_T~5F!JC%h2|Qm0p;m}Llb521g!Wjh}CIo zED4AA(4Z?`Vj8ERH0*-mPy_@j3j@O?!7x!USp3&P|09>}DOl<#8mjTwoyFS;;fH?p zAJxm7fN=(Zfiz%%e_lWY91ep6oq<1ma9KDl9{L6J*z?rA`IA07sSM=>|g2&SqeOFzh+d3Z3w6)#A#jZkzB9L~n3rEPy0fdD$ I4UvHV0mU){?EnA( literal 0 HcmV?d00001 diff --git a/tex/figures/mcfg/mcfg_2.svg b/tex/figures/mcfg/mcfg_2.svg new file mode 100644 index 0000000..43b494b --- /dev/null +++ b/tex/figures/mcfg/mcfg_2.svg @@ -0,0 +1,157 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + m-MCFL(1) + m-MCFL(2) + m-MCFL(r) + m-MCFL(r+1) + m-MCFL + + + + diff --git a/tex/figures/multi/graph0.tex b/tex/figures/multi/graph0.tex new file mode 100644 index 0000000..9f1a442 --- /dev/null +++ b/tex/figures/multi/graph0.tex @@ -0,0 +1,18 @@ +\begin{tikzpicture}[node distance=2cm, shorten >=1pt,on grid,auto] + \node[state] (q_0) {$0$}; + \node[state] (q_1) [right=of q_0] {$1$}; + \node[state] (q_2) [right=of q_1] {$2$}; + \node[state] (q_6) [below=of q_2] {$6$}; + \node[state] (q_3) [right=of q_2] {$3$}; + \node[state] (q_5) [right=of q_6] {$5$}; + \node[state] (q_4) [right=of q_3] {$4$}; + + \path[->] + (q_0) edge node {a} (q_1) + (q_1) edge node {b} (q_2) + (q_1) edge node {a} (q_6) + (q_2) edge node {c} (q_3) + (q_3) edge node {c} (q_4) + (q_6) edge node {b} (q_5) + (q_5) edge node {c} (q_4); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph0.tex b/tex/figures/tensor/graph0.tex new file mode 100644 index 0000000..1107ee5 --- /dev/null +++ b/tex/figures/tensor/graph0.tex @@ -0,0 +1,20 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge[left] node {a} (q_1) + (q_1) edge[above] node {a} (q_2) + edge[bend left, above] node {\textbf{S}} (q_3) + (q_2) edge[below] node {a} (q_0) + edge[bend left, above] node {b} (q_3) + (q_3) edge[bend left, below] node {b} (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph1.tex b/tex/figures/tensor/graph1.tex new file mode 100644 index 0000000..678bc8e --- /dev/null +++ b/tex/figures/tensor/graph1.tex @@ -0,0 +1,21 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge[left] node {a} (q_1) + edge[bend right, below] node {\textbf{S}} (q_2) + (q_1) edge[above] node {a} (q_2) + edge[bend left, above] node {S} (q_3) + (q_2) edge[below] node {a} (q_0) + edge[bend left, above] node {b} (q_3) + (q_3) edge[bend left, below] node {b} (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph2.tex b/tex/figures/tensor/graph2.tex new file mode 100644 index 0000000..4965a0f --- /dev/null +++ b/tex/figures/tensor/graph2.tex @@ -0,0 +1,21 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge[left] node {a} (q_1) + edge[bend right, below] node {S} (q_2) + (q_1) edge[above] node {a} (q_2) + edge[bend left, above, out=30, in=135] node {S} (q_3) + (q_2) edge[below] node {a} (q_0) + edge[bend left, above] node {b, \textbf{S}} (q_3) + (q_3) edge[bend left, below] node {b} (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph3.tex b/tex/figures/tensor/graph3.tex new file mode 100644 index 0000000..cb1ad3e --- /dev/null +++ b/tex/figures/tensor/graph3.tex @@ -0,0 +1,21 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge[left] node {a} (q_1) + edge[bend right, below] node {S} (q_2) + (q_1) edge[above] node {a, \textbf{S}} (q_2) + edge[bend left, above, out=30, in=135] node {S} (q_3) + (q_2) edge[below] node {a} (q_0) + edge[bend left, above] node {b, S} (q_3) + (q_3) edge[bend left, below] node {b} (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph4.tex b/tex/figures/tensor/graph4.tex new file mode 100644 index 0000000..a674ced --- /dev/null +++ b/tex/figures/tensor/graph4.tex @@ -0,0 +1,22 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge[left] node {a} (q_1) + edge[bend right, below] node {S} (q_2) + edge[bend right, below, out=330, in=225] node {\textbf{S}} (q_3) + (q_1) edge[above] node {a, S} (q_2) + edge[bend left, above, out=30, in=135] node {S} (q_3) + (q_2) edge[below] node {a} (q_0) + edge[bend left, above] node {b, S} (q_3) + (q_3) edge[bend left, below] node {b} (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/graph5.tex b/tex/figures/tensor/graph5.tex new file mode 100644 index 0000000..dc0b0b1 --- /dev/null +++ b/tex/figures/tensor/graph5.tex @@ -0,0 +1,23 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \node[state] (q_3) [right=1.5cm of q_2] {$3$}; + \path[->] + (q_0) edge[left] node {a} (q_1) + edge[bend right, below] node {S} (q_2) + edge[bend right, below, out=330, in=225] node {S} (q_3) + (q_1) edge[above] node {a, S} (q_2) + edge[bend left, above, out=30, in=135] node {S} (q_3) + (q_2) edge[below] node {a} (q_0) + edge[bend left, above] node {b, S} (q_3) + edge[loop right] node {\textbf{S}} () + (q_3) edge[bend left, below] node {b} (q_2); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/figures/tensor/recursive.tex b/tex/figures/tensor/recursive.tex new file mode 100644 index 0000000..36015c3 --- /dev/null +++ b/tex/figures/tensor/recursive.tex @@ -0,0 +1,16 @@ +\begin{tikzpicture}[] + % Apex angle 60 degrees + \node[isosceles triangle, + isosceles triangle apex angle=60, + draw=none,fill=none, + minimum size=2cm] (T60) at (3,0){}; + + + \node[state, initial, accepting] (q_0) at (T60.right corner) {$0$}; + \node[state] (q_1) at (T60.left corner) {$1$}; + \node[state] (q_2) at (T60.apex) {$2$}; + \path[->] + (q_0) edge[left] node {a} (q_1) + (q_1) edge[above] node {S} (q_2) + (q_2) edge[below] node {b} (q_0); +\end{tikzpicture} \ No newline at end of file diff --git a/tex/main.tex b/tex/main.tex index 5772ee8..d18ab4b 100644 --- a/tex/main.tex +++ b/tex/main.tex @@ -50,6 +50,22 @@ \input{FormalLanguageTheoryIntro} \input{RegularLanguages} \input{Context-Free_Languages} +% \input{Multiple_Context-Free_Languages} +% %\input{ConjunctiveAndBooleanLanguages} +% \input{FLPQ} +% \input{RPQ} +% %\input{CFPQ} +% \input{CYK_for_CFPQ} +% \input{Matrix-based_CFPQ} +% \input{TensorProduct} +% \input{SPPF} +% \input{GLL-based_CFPQ} +% \input{GLR-based_CFPQ} +% %\input{CombinatorsForCFPQ} +% \input{Multiple_Context-Free_Language_Reachability} +% %\input{DerivativesForCFPQ} +% %\input{CFPQ_to_Datalog} +% \input{Conclusion} \backmatter \setchapterstyle{plain} diff --git a/tex/old_FormalLanguageConstrainedReachabilityLectureNotes.tex b/tex/old_FormalLanguageConstrainedReachabilityLectureNotes.tex new file mode 100644 index 0000000..ec17188 --- /dev/null +++ b/tex/old_FormalLanguageConstrainedReachabilityLectureNotes.tex @@ -0,0 +1,204 @@ +%\documentclass[a4paper,12pt]{article} % standard LaTeX, 12 point type +\documentclass[12pt, a4paper, table]{book} + +\usepackage{algpseudocode} +\usepackage{algorithm} +\usepackage{algorithmicx} + +\usepackage{geometry} +\usepackage{amsfonts,latexsym} +\usepackage{amsthm, amsmath} +\usepackage{amssymb} +\usepackage[utf8]{inputenc} % Кодировка +\usepackage[english,russian]{babel} % Многоязычность +\usepackage{mathtools} +\usepackage{hyperref} +\usepackage[dvipsnames]{xcolor} +\usepackage{tikz} +\usepackage{dsfont} +\usepackage{multicol} +\usepackage[bb=boondox]{mathalfa} +\usepackage{subcaption} +\usepackage{fontawesome} + +\usetikzlibrary{fit,calc,automata,positioning} +\usetikzlibrary{shapes.geometric} +\usetikzlibrary{decorations.pathmorphing} + +\theoremstyle{definition} +\newtheorem{definition}{Определение}[section] +\newtheorem{example}{Пример}[section] +\newtheorem{theorem}{Теорема}[section] +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{lemma}[theorem]{Лемма} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\newtheorem{note}[theorem]{Утверждение} + + +% unnumbered environments: + +\theoremstyle{remark} +\newtheorem*{remark}{Remark} +%\newtheorem*{notation}{Notation} + +\setlength{\parskip}{5pt plus 2pt minus 1pt} +%\setlength{\parindent}{0pt} + +\tikzset{snake it/.style={decorate, decoration=snake}} +\tikzset{ + side by side/.style 2 args={ + line width=2pt, + #1, + postaction={ + clip,postaction={draw,#2} + } + } +} + +\algtext*{EndWhile}% Remove "end while" text +\algtext*{EndIf}% Remove "end if" text +\algtext*{EndFor}% Remove "end for" text +\algtext*{EndFunction}% Remove "end function" text + + +% \usepackage{color} +\usepackage{listings} +\usepackage{caption} +\usepackage{graphicx} +\usepackage{ucs} + +% \graphicspath{{pics/}} + +%\geometry{left=2cm} +%\geometry{right=1.5cm} +%\geometry{top=2cm} +%\geometry{bottom=2cm} + + + + +%\lstnewenvironment{algorithm}[1][] +%{ +% \lstset{ +% frame=tB, +% numbers=left, +% mathescape=true, +% numberstyle=\small, +% basicstyle=\small, +% inputencoding=utf8, +% extendedchars=\true, +% keywordstyle=\color{black}\bfseries, +% keywords={,function, procedure, return, datatype, function, in, if, else, for, foreach, while, denote, do, and, then, assert,} +% numbers=left, +% xleftmargin=.04\textwidth, +% #1 % this is to add specific settings to an usage of this environment (for instnce, the caption and referable label) +% } +%} +%{} + +\newcommand{\tab}[1][0.3cm]{\ensuremath{\hspace*{#1}}} + +\newcommand{\rvline}{\hspace*{-\arraycolsep}\vline\hspace*{-\arraycolsep}} + +\newcommand{\derives}[1][*]{\xRightarrow[]{#1}} +\newcommand{\first}[1][1]{\textsc{first}_{#1}} +\newcommand{\follow}[1][1]{\textsc{follow}_{#1}} + +\newcommand{\highlight}[2][yellow]{\mathchoice% + {\colorbox{#1}{$\displaystyle#2$}}% + {\colorbox{#1}{$\textstyle#2$}}% + {\colorbox{#1}{$\scriptstyle#2$}}% + {\colorbox{#1}{$\scriptscriptstyle#2$}}}% + +\setcounter{MaxMatrixCols}{20} + + +\tikzset{ +%->, % makes the edges directed +%>=stealth’, % makes the arrow heads bold +node distance=4cm, % specifies the minimum distance between two nodes. Change if necessary. +%every state/.style={thick, fill=gray!10}, % sets the properties for each ’state’ node +initial text=$ $, % sets the text that appears on the start arrow +} + +\tikzstyle{symbol_node} = [shape=rectangle, rounded corners, draw, align=center] + +\tikzstyle{r_state} = [shape=rectangle, draw, minimum size=0.2cm] + +\tikzstyle{num_state} = [draw=none, fill=none, anchor=south west, red] + +\tikzstyle{prod_node} = [shape=rectangle, draw, align=center] + +\tikzset{ + between/.style args={#1 and #2}{ + at = ($(#1)!0.5!(#2)$) + }, + >= stealth, + every state/.style={minimum size=1pt} +} + +%every node/.style = {shape=rectangle, rounded corners, +% draw, align=center, +% top color=white, bottom color=blue!20} + +\newcommand{\bfgray}[1]{\cellcolor{lightgray}\textbf{#1}} + +\newenvironment{scaledalign}[4] + { + \begingroup + #1 + \setlength\arraycolsep{#2} + \renewcommand{\arraystretch}{#3} + \begin{center} + \begin{equation} + \begin{aligned} + #4 + } + { + \end{aligned} + \end{equation} + \end{center} + \endgroup + } + +\title{О достижимости с ограничениями в терминах формальных языков} +\author{Семён Григорьев} +\date{\today} + +\begin{document} +\maketitle +\newpage +\tableofcontents +\newpage + + +\input{List_of_contributors} +\input{Introduction} +\input{LinearAlgebra} +\input{GraphTheoryIntro} +\input{FormalLanguageTheoryIntro} +\input{RegularLanguages} +\input{Context-Free_Languages} +\input{Multiple_Context-Free_Languages} +%\input{ConjunctiveAndBooleanLanguages} +\input{FLPQ} +\input{RPQ} +%\input{CFPQ} +\input{CYK_for_CFPQ} +\input{Matrix-based_CFPQ} +\input{TensorProduct} +\input{SPPF} +\input{GLL-based_CFPQ} +\input{GLR-based_CFPQ} +%\input{CombinatorsForCFPQ} +\input{Multiple_Context-Free_Language_Reachability} +%\input{DerivativesForCFPQ} +%\input{CFPQ_to_Datalog} +\input{Conclusion} + +\bibliographystyle{abbrv} +\bibliography{FormalLanguageConstrainedReachabilityLectureNotes} + + +\end{document} From 2b7663c5f1b0561c578f1fe72e38665ddb962559 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Wed, 19 Jun 2024 21:10:55 +0300 Subject: [PATCH 23/29] Restore name of the main file --- .github/workflows/main.yml | 6 +----- .gitignore | 1 - ...> FormalLanguageConstrainedReachabilityLectureNotes.tex} | 0 3 files changed, 1 insertion(+), 6 deletions(-) rename tex/{main.tex => FormalLanguageConstrainedReachabilityLectureNotes.tex} (100%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0d4ae26..c6c5fcc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,16 +23,12 @@ jobs: - name: Compile LaTeX document uses: xu-cheng/latex-action@v3 with: - root_file: tex/main.tex + root_file: tex/FormalLanguageConstrainedReachabilityLectureNotes.tex work_in_root_file_dir: true latexmk_use_lualatex: true extra_system_packages: "font-liberation" latexmk_shell_escape: true - - name: Rename PDF - run: | - mv tex/main.pdf tex/FormalLanguageConstrainedReachabilityLectureNotes.pdf - - name: Upload PDF file uses: actions/upload-artifact@v4 with: diff --git a/.gitignore b/.gitignore index bd3b898..3263f3f 100644 --- a/.gitignore +++ b/.gitignore @@ -278,4 +278,3 @@ TSWLatexianTemp* tex/FormalLanguageConstrainedReachabilityLectureNotes.pdf tex/figures/externalized/* !tex/figures/externalized/.gitkeep -tex/main.pdf diff --git a/tex/main.tex b/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex similarity index 100% rename from tex/main.tex rename to tex/FormalLanguageConstrainedReachabilityLectureNotes.tex From d0bab18aa506d16a3551ecbd4557838f146701e8 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Wed, 19 Jun 2024 21:34:47 +0300 Subject: [PATCH 24/29] Add Makefile --- tex/Makefile | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tex/Makefile diff --git a/tex/Makefile b/tex/Makefile new file mode 100644 index 0000000..e889e56 --- /dev/null +++ b/tex/Makefile @@ -0,0 +1,27 @@ +NAME = FormalLanguageConstrainedReachabilityLectureNotes +ENGINE = lualatex # Only `xelatex` or `lualatex` are allowed here + +.PHONY: $(NAME).pdf clean dist-clean format + +all: $(NAME).pdf + +$(NAME).pdf: + latexmk -$(ENGINE) -synctex=1 -interaction=nonstopmode -file-line-error -shell-escape $(NAME).tex + +clean: + latexmk -c $(NAME).tex + +dist-clean: + latexmk -C $(NAME).tex + +# https://stackoverflow.com/a/12959694 +# Make does not offer a recursive wildcard function, so here's one: +rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) + +FILES_TO_FORMAT := $(call rwildcard,./,*.tex) \ + $(call rwildcard,./,*.cls) \ + $(call rwildcard,./,*.bib) +#$(info $(FILES_TO_FORMAT)) + +format: + $(foreach file, $(FILES_TO_FORMAT), latexindent -l -s -o=$(file) -m $(file);) From f5c255792f66de638213245961c4f4437de8e0c8 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Wed, 19 Jun 2024 21:35:23 +0300 Subject: [PATCH 25/29] Add caching of pictures in CI --- .github/workflows/main.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c6c5fcc..6380da9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,6 +20,12 @@ jobs: - name: Set up Git repository uses: actions/checkout@v4 + - name: Cache TikZ externalized pictures + uses: actions/cache@v4 + with: + path: tex/figures/externalized + key: tikz-externalized + - name: Compile LaTeX document uses: xu-cheng/latex-action@v3 with: From 4ddcece4c287ff9a730ec3f198bc9c4fc13866a8 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Wed, 19 Jun 2024 22:00:41 +0300 Subject: [PATCH 26/29] Comment more incomplete parts --- ...ageConstrainedReachabilityLectureNotes.tex | 4 +- tex/GraphTheoryIntro.tex | 221 ++++++------- tex/LinearAlgebra.tex | 299 +++++++++--------- tex/Matrix-based_CFPQ.tex | 65 ++-- 4 files changed, 296 insertions(+), 293 deletions(-) diff --git a/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex b/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex index d18ab4b..453f00e 100644 --- a/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex +++ b/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex @@ -50,7 +50,7 @@ \input{FormalLanguageTheoryIntro} \input{RegularLanguages} \input{Context-Free_Languages} -% \input{Multiple_Context-Free_Languages} +% \input{Multiple_Context-Free_Languages} % FIXME: Переписать главу % %\input{ConjunctiveAndBooleanLanguages} % \input{FLPQ} % \input{RPQ} @@ -62,7 +62,7 @@ % \input{GLL-based_CFPQ} % \input{GLR-based_CFPQ} % %\input{CombinatorsForCFPQ} -% \input{Multiple_Context-Free_Language_Reachability} +% \input{Multiple_Context-Free_Language_Reachability} % FIXME: Исправить главу % %\input{DerivativesForCFPQ} % %\input{CFPQ_to_Datalog} % \input{Conclusion} diff --git a/tex/GraphTheoryIntro.tex b/tex/GraphTheoryIntro.tex index 3f6b624..7198172 100644 --- a/tex/GraphTheoryIntro.tex +++ b/tex/GraphTheoryIntro.tex @@ -551,113 +551,114 @@ \section{Алгоритм Флойда-Уоршелла} Идеи, заложенные в алгоритме Флойда-Уоршелла, а также возможность абстрагировать его, помогут нам в дальнейшем предложить алгоритм для задачи достижимости с ограничениями в терминах формальных языков. -\section{Анализ путей в графе и линейная алгебра} - -В данной главе мы рассмотрим некоторые связи% -\sidenote{Связь между графами и линейной алгеброй~--- обширная область, в которой можно даже выделить отдельные направления, такие как спектральная теория графов. - С точки зрения практики данная связь также подмечена давно и более полно с ней можно ознакомиться, например, в работах~\cite{doi:10.1137/1.9780898719918, Davis2018Algorithm9S}. - Кроме этого, много полезной информации можно найти на сайте \url{https://graphblas.github.io/GraphBLAS-Pointers/}.} -между графами и операциями над ними и матрицами и операциями над матрицами. - -Как мы видели, достаточно естественное представление графа~--- это его матрица смежности. -Далее можно заметить некоторое сходство между определением матричного умножения~\ref{def:MxM} и мыслями, которыми мы руководствовались, вводя операцию $\otimes$ (\ref{itm:otimesIntro}). -Действительно, пусть есть матрица $M$ размера $n \times n$ над $\BbbG = (S, \oplus, \otimes)$% -\sidenote{Здесь мы уже сталкиваемся с тем, что могут иметь смысл относительно экзотические алгебраические структуры. - Действительно, как мы выяснили, матрица смежности может быть определена на чем-то более бедным, чем полукольцо, а матричное умножение мы определяли над полукольцом. - Но если задуматься, то и для определения произведения матриц полукольцо вовсе необязательно, достаточно более бедной структуры.}~--- матрица смежности графа. -Умножим её саму на себя: вычислим $M'= M \cdot M$. -Тогда, по~\ref{def:MxM}, $M'[i, j] = \bigoplus_{l \in [0 \rng n-1]} M[i, l] \otimes M[l, j]$. -Размер $M'$ также $n \times n$. -То есть $M'$ задаёт такой граф, что в нём будет путь со свойством, являющимся агрегацией свойств всех путей, составленных из двух подпутей в исходном графе. -А именно, если в исходном графе есть путь из $i$ в $l$ с некоторым свойством (его значение хранится в $M[i, l]$), и был путь из $l$ в $j$ (его значение хранится в $M[l,j]$), то в новом графе свойство $M[i, l] \otimes M[l, j]$ аддитивно (используя $\oplus$) учтётся в свойстве пути из $i$ в $j$. - -Таким образом, произведение матриц смежности соответствует обработке информации о путях интересующим нас образом. -Это наблюдение позволяет предложить решение задач анализа свойств путей, основанное на операциях над матрицами. -Рассмотрим такое решение для задачи о кратчайших путях. - -Пусть $D_k$~--- матрица кратчайших путей, состоящих не более чем из $k$ рёбер. -То есть $D_k[i, j]$~--- это длина кратчайшего пути из вершины $i$ в вершину $j$, такого, что он состоит не более чем из $k$ ребер. -Если такого пути нет, то $D_k[i, j] = +\infty$. - -Таким образом, $D_1 = M$, где $M$~--- это матрица смежности исходного графа, а решением APSP является $D_{n-1}$, вычисляемая с помощью следующего рекуррентного соотношения: -\begin{gather*} - D(1) = M \\ - D(2) = D(1) \cdot M = M^2 \\ - D(3) = D(2) \cdot M = M^3 \\ - \vdots \\ - D(n - 1) = D(n - 2) \cdot M = M^{(n - 1)} -\end{gather*} - -Здесь мы пользуемся той особенностью задачи, что кратчайший путь в ориентированном графе (без отрицательных циклов) не может быть длиннее $n$% -\sidenote{Раз отрицательных циклов нету, то проходить через одну вершину, коих $n$, больше одного раза бессмысленно.}. -Более того, мы пользуемся тем, что используемая структура именно полукольцо, а исходное отношение рефлексивно% -\sidenote{ - Тот факт, что в любой вершине есть петля с весом 0, а 0~--- нейтральный для $\otimes$, позволяет не суммировать матрицы. - Итоговая матрица содержит данные о путях длины \emph{не больше чем} вычисляемая степень, хотя должна бы содержать данные о путях ровно и только такой длины. - Предлагается самостоятельно исследовать данный феномен.}. - -Таким образом, решение APSP сведено к произведению матриц над тропическим полукольцом, однако вычислительная сложность решения слишком большая: $O(n K(n))$, где $K(n)$~--- сложность алгоритма умножения матриц. - -Чтобы улучшить сложность, заметим, что, например, $D_3$ вычислять не обязательно, так как можно сразу вычислить $D_4$ как $D_2 \cdot D_2$. - -В итоге получим следующую последовательность вычислений: -\begin{gather*} - D_1 = M \\ - D_2 = M^2 = M \cdot M \\ - D_4 = M^4 = M^2 \cdot M^2 \\ - D_8 = M^8 = M^4 \cdot M^4 \\ - \vdots \\ - D_{2^{\log(n-1)}} = M^{2^{\log(n-1)}} = M^{2^{\log(n-1)} - 1} \cdot M^{2^{\log(n-1)} - 1} \\ - D_{n-1} = D_{2^{\log(n-1)}} -\end{gather*} - -Теперь вместо $n$ итераций нам нужно $\log{n}$, а итоговая сложность решения~--- $O(\log{n} K(n))$% -\sidenote{ - Заметим, что это оценка для худшего случая. - На практике при использовании данного подхода можно прекращать вычисления как только при двух последовательных шагах получились одинаковые матрицы ($D_i = D_{i-1}$). - Это приводит нас к понятию \emph{неподвижной точки}, обсуждение которого лежит за рамками повествования.}. -Данный алгоритм называется \emph{repeated squaring}% -\sidenote{Пример решения APSP с помощью repeated squaring: \url{http://users.cecs.anu.edu.au/~Alistair.Rendell/Teaching/apac_comp3600/module4/all_pairs_shortest_paths.xhtml}}. -Здесь мы предполагаем, что $n-1 = 2^k$ для какого-то $k$. -На практике такое верно далеко не всегда. -Если это условие не выполняется, то необходимо взять ближайшую сверху степень двойки% -\sidenote{ - Кажется, что это приведёт к избыточным вычислениям. - Попробуйте оценить, на сколько много лишних вычислений будет сделано в худшем случае.}. - -Таким образом, APSP сводится к умножению матриц над полукольцом, что, к сожалению, не позволяет этим путём получить истинно субкубический алгоритм для задачи. -Тем не менее, позволяет получить слегка субкубический. -Приведем некоторые работы по APSP для ориентированных графов с вещественными весами (здесь $n$~--- количество вершин в графе), по которым можно более детально ознакомиться как с историей вопроса, так и с текущими результатами: -\begin{itemize} - \item M.L. Fredman (1976)~--- $O(n^3(\log \log n / \log n)^\frac{1}{3})$~--- использование дерева решений~\sidecite{FredmanAPSP1976} - \item W. Dobosiewicz (1990)~--- $O(n^3 / \sqrt{\log n})$~--- использование операций на Word Random Access Machine~\sidecite{Dobosiewicz1990} - \item T. Takaoka (1992)~--- $O(n^3 \sqrt{\log \log n / \log n})$~--- использование таблицы поиска~\sidecite{Takaoka1992} - \item Y. Han (2004)~--- $O(n^3 (\log \log n / \log n)^\frac{5}{7})$~\sidecite{Han2004} - \item T. Takoaka (2004)~--- $O(n^3 (\log \log n)^2 / \log n)$~\sidecite{Takaoka2004} - \item T. Takoaka (2005)~--- $O(n^3 \log \log n / \log n)$~\sidecite{Takaoka2005} - \item U. Zwick (2004)~--- $O(n^3 \sqrt{\log \log n} / \log n)$~\sidecite{Zwick2004} - \item T.M. Chan (2006)~--- $O(n^3 / \log n)$~--- многомерный принцип \enquote{разделяй и властвуй}~\sidecite{Chan2008} -\end{itemize} - -Вопрос же о истинно субкубических алгоритмах решения APSP всё ещё открыт~\sidecite{Chan2010} и активно обсуждается в научном сообществе. - -Аналогичным образом можно свести транзитивное замыкание к матричным операциям. -Предлагаем проделать это самостоятельно, заодно обратив внимание на важность рефлексивности (в примере~\ref{exmpl:transitiveClosure} её нет). - -Заметим, что оптимизация, связанная с возведением в квадрат возможна только при ассоциативности произведения матриц, что зависит от свойств алгебраической структуры, над которой построены матрицы. -Для полукольца такая оптимизация законна, однако в некоторых случаях её применить нельзя. -Таким случаем как раз и будет рассматриваемая в нашей работе задача. -Поэтому построение алгоритма её решения через операции над матрицами, хотя и будет основано на указанных выше соображениях, но будет сопряжено с некоторыми трудностями. - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item Реализуйте абстракцию полукольца, позволяющую конструировать полукольца с произвольными операциями. -% \item Реализуйте алгоритм произведения матриц над произвольным полукольцом. Используйте результат решения предыдущей задачи. -% \item Используя результаты предыдущих задач, реализуйте алгоритм построения транзитивного замыкания через произведение матриц. -% \item Используя результаты предыдущих задач, реализуйте алгоритм решения задачи APSP для ориентированного через произведение матриц. -% \item Используя существующую библиотеку линейной алгебры для CPU, решите задачу построения транзитивного замыкания графа. -% \item Используя существующую библиотеку линейной алгебры для CPU, решите задачу APSP для ориентированного графа. -% \item Используя существующую библиотеку линейной алгебры для GPGPU, решите задачу построения транзитивного замыкания графа. -% \item Используя существующую библиотеку линейной алгебры для GPGPU, решите задачу APSP для ориентированного графа. -% \item Сравните произволительность решений предыдущих задач -%\end{enumerate} +%% FIXME: Исправить раздел +% \section{Анализ путей в графе и линейная алгебра} + +% В данной главе мы рассмотрим некоторые связи% +% \sidenote{Связь между графами и линейной алгеброй~--- обширная область, в которой можно даже выделить отдельные направления, такие как спектральная теория графов. +% С точки зрения практики данная связь также подмечена давно и более полно с ней можно ознакомиться, например, в работах~\cite{doi:10.1137/1.9780898719918, Davis2018Algorithm9S}. +% Кроме этого, много полезной информации можно найти на сайте \url{https://graphblas.github.io/GraphBLAS-Pointers/}.} +% между графами и операциями над ними и матрицами и операциями над матрицами. + +% Как мы видели, достаточно естественное представление графа~--- это его матрица смежности. +% Далее можно заметить некоторое сходство между определением матричного умножения~\ref{def:MxM} и мыслями, которыми мы руководствовались, вводя операцию $\otimes$ (\ref{itm:otimesIntro}). +% Действительно, пусть есть матрица $M$ размера $n \times n$ над $\BbbG = (S, \oplus, \otimes)$% +% \sidenote{Здесь мы уже сталкиваемся с тем, что могут иметь смысл относительно экзотические алгебраические структуры. +% Действительно, как мы выяснили, матрица смежности может быть определена на чем-то более бедным, чем полукольцо, а матричное умножение мы определяли над полукольцом. +% Но если задуматься, то и для определения произведения матриц полукольцо вовсе необязательно, достаточно более бедной структуры.}~--- матрица смежности графа. +% Умножим её саму на себя: вычислим $M'= M \cdot M$. +% Тогда, по~\ref{def:MxM}, $M'[i, j] = \bigoplus_{l \in [0 \rng n-1]} M[i, l] \otimes M[l, j]$. +% Размер $M'$ также $n \times n$. +% То есть $M'$ задаёт такой граф, что в нём будет путь со свойством, являющимся агрегацией свойств всех путей, составленных из двух подпутей в исходном графе. +% А именно, если в исходном графе есть путь из $i$ в $l$ с некоторым свойством (его значение хранится в $M[i, l]$), и был путь из $l$ в $j$ (его значение хранится в $M[l,j]$), то в новом графе свойство $M[i, l] \otimes M[l, j]$ аддитивно (используя $\oplus$) учтётся в свойстве пути из $i$ в $j$. + +% Таким образом, произведение матриц смежности соответствует обработке информации о путях интересующим нас образом. +% Это наблюдение позволяет предложить решение задач анализа свойств путей, основанное на операциях над матрицами. +% Рассмотрим такое решение для задачи о кратчайших путях. + +% Пусть $D_k$~--- матрица кратчайших путей, состоящих не более чем из $k$ рёбер. +% То есть $D_k[i, j]$~--- это длина кратчайшего пути из вершины $i$ в вершину $j$, такого, что он состоит не более чем из $k$ ребер. +% Если такого пути нет, то $D_k[i, j] = +\infty$. + +% Таким образом, $D_1 = M$, где $M$~--- это матрица смежности исходного графа, а решением APSP является $D_{n-1}$, вычисляемая с помощью следующего рекуррентного соотношения: +% \begin{gather*} +% D(1) = M \\ +% D(2) = D(1) \cdot M = M^2 \\ +% D(3) = D(2) \cdot M = M^3 \\ +% \vdots \\ +% D(n - 1) = D(n - 2) \cdot M = M^{(n - 1)} +% \end{gather*} + +% Здесь мы пользуемся той особенностью задачи, что кратчайший путь в ориентированном графе (без отрицательных циклов) не может быть длиннее $n$% +% \sidenote{Раз отрицательных циклов нету, то проходить через одну вершину, коих $n$, больше одного раза бессмысленно.}. +% Более того, мы пользуемся тем, что используемая структура именно полукольцо, а исходное отношение рефлексивно% +% \sidenote{ +% Тот факт, что в любой вершине есть петля с весом 0, а 0~--- нейтральный для $\otimes$, позволяет не суммировать матрицы. +% Итоговая матрица содержит данные о путях длины \emph{не больше чем} вычисляемая степень, хотя должна бы содержать данные о путях ровно и только такой длины. +% Предлагается самостоятельно исследовать данный феномен.}. + +% Таким образом, решение APSP сведено к произведению матриц над тропическим полукольцом, однако вычислительная сложность решения слишком большая: $O(n K(n))$, где $K(n)$~--- сложность алгоритма умножения матриц. + +% Чтобы улучшить сложность, заметим, что, например, $D_3$ вычислять не обязательно, так как можно сразу вычислить $D_4$ как $D_2 \cdot D_2$. + +% В итоге получим следующую последовательность вычислений: +% \begin{gather*} +% D_1 = M \\ +% D_2 = M^2 = M \cdot M \\ +% D_4 = M^4 = M^2 \cdot M^2 \\ +% D_8 = M^8 = M^4 \cdot M^4 \\ +% \vdots \\ +% D_{2^{\log(n-1)}} = M^{2^{\log(n-1)}} = M^{2^{\log(n-1)} - 1} \cdot M^{2^{\log(n-1)} - 1} \\ +% D_{n-1} = D_{2^{\log(n-1)}} +% \end{gather*} + +% Теперь вместо $n$ итераций нам нужно $\log{n}$, а итоговая сложность решения~--- $O(\log{n} K(n))$% +% \sidenote{ +% Заметим, что это оценка для худшего случая. +% На практике при использовании данного подхода можно прекращать вычисления как только при двух последовательных шагах получились одинаковые матрицы ($D_i = D_{i-1}$). +% Это приводит нас к понятию \emph{неподвижной точки}, обсуждение которого лежит за рамками повествования.}. +% Данный алгоритм называется \emph{repeated squaring}% +% \sidenote{Пример решения APSP с помощью repeated squaring: \url{http://users.cecs.anu.edu.au/~Alistair.Rendell/Teaching/apac_comp3600/module4/all_pairs_shortest_paths.xhtml}}. +% Здесь мы предполагаем, что $n-1 = 2^k$ для какого-то $k$. +% На практике такое верно далеко не всегда. +% Если это условие не выполняется, то необходимо взять ближайшую сверху степень двойки% +% \sidenote{ +% Кажется, что это приведёт к избыточным вычислениям. +% Попробуйте оценить, на сколько много лишних вычислений будет сделано в худшем случае.}. + +% Таким образом, APSP сводится к умножению матриц над полукольцом, что, к сожалению, не позволяет этим путём получить истинно субкубический алгоритм для задачи. +% Тем не менее, позволяет получить слегка субкубический. +% Приведем некоторые работы по APSP для ориентированных графов с вещественными весами (здесь $n$~--- количество вершин в графе), по которым можно более детально ознакомиться как с историей вопроса, так и с текущими результатами: +% \begin{itemize} +% \item M.L. Fredman (1976)~--- $O(n^3(\log \log n / \log n)^\frac{1}{3})$~--- использование дерева решений~\sidecite{FredmanAPSP1976} +% \item W. Dobosiewicz (1990)~--- $O(n^3 / \sqrt{\log n})$~--- использование операций на Word Random Access Machine~\sidecite{Dobosiewicz1990} +% \item T. Takaoka (1992)~--- $O(n^3 \sqrt{\log \log n / \log n})$~--- использование таблицы поиска~\sidecite{Takaoka1992} +% \item Y. Han (2004)~--- $O(n^3 (\log \log n / \log n)^\frac{5}{7})$~\sidecite{Han2004} +% \item T. Takoaka (2004)~--- $O(n^3 (\log \log n)^2 / \log n)$~\sidecite{Takaoka2004} +% \item T. Takoaka (2005)~--- $O(n^3 \log \log n / \log n)$~\sidecite{Takaoka2005} +% \item U. Zwick (2004)~--- $O(n^3 \sqrt{\log \log n} / \log n)$~\sidecite{Zwick2004} +% \item T.M. Chan (2006)~--- $O(n^3 / \log n)$~--- многомерный принцип \enquote{разделяй и властвуй}~\sidecite{Chan2008} +% \end{itemize} + +% Вопрос же о истинно субкубических алгоритмах решения APSP всё ещё открыт~\sidecite{Chan2010} и активно обсуждается в научном сообществе. + +% Аналогичным образом можно свести транзитивное замыкание к матричным операциям. +% Предлагаем проделать это самостоятельно, заодно обратив внимание на важность рефлексивности (в примере~\ref{exmpl:transitiveClosure} её нет). + +% Заметим, что оптимизация, связанная с возведением в квадрат возможна только при ассоциативности произведения матриц, что зависит от свойств алгебраической структуры, над которой построены матрицы. +% Для полукольца такая оптимизация законна, однако в некоторых случаях её применить нельзя. +% Таким случаем как раз и будет рассматриваемая в нашей работе задача. +% Поэтому построение алгоритма её решения через операции над матрицами, хотя и будет основано на указанных выше соображениях, но будет сопряжено с некоторыми трудностями. + +% %\section{Вопросы и задачи} +% %\begin{enumerate} +% % \item Реализуйте абстракцию полукольца, позволяющую конструировать полукольца с произвольными операциями. +% % \item Реализуйте алгоритм произведения матриц над произвольным полукольцом. Используйте результат решения предыдущей задачи. +% % \item Используя результаты предыдущих задач, реализуйте алгоритм построения транзитивного замыкания через произведение матриц. +% % \item Используя результаты предыдущих задач, реализуйте алгоритм решения задачи APSP для ориентированного через произведение матриц. +% % \item Используя существующую библиотеку линейной алгебры для CPU, решите задачу построения транзитивного замыкания графа. +% % \item Используя существующую библиотеку линейной алгебры для CPU, решите задачу APSP для ориентированного графа. +% % \item Используя существующую библиотеку линейной алгебры для GPGPU, решите задачу построения транзитивного замыкания графа. +% % \item Используя существующую библиотеку линейной алгебры для GPGPU, решите задачу APSP для ориентированного графа. +% % \item Сравните произволительность решений предыдущих задач +% %\end{enumerate} diff --git a/tex/LinearAlgebra.tex b/tex/LinearAlgebra.tex index 2f2774f..6ddf08a 100644 --- a/tex/LinearAlgebra.tex +++ b/tex/LinearAlgebra.tex @@ -651,152 +651,153 @@ \section{Матрицы и вектора} \end{example} \endgroup -\section{Теоретическая сложность умножения матриц} - -В рамках такого раздела теории сложности, как мелкозернистая сложность (fine-grained complexity) задача умножения двух матриц оказалась достаточно важной, так как через вычислительную сложность этой задачи можно оценить сложность большого класса различных задач. -С примерами таких задач можно ознакомиться в работе~\sidecite{Williams:2010:SEP:1917827.1918339}. Поэтому рассмотрим алгоритмы нахождения произведения двух матриц более подробно. -Далее для простоты мы будем предполагать, что перемножаются две квадратные матрицы одинакового размера $n \times n$. - -Для начала построим наивный алгоритм, сконструированный на основе определения произведения матриц. -Такой алгоритм представлен на листинге~\ref{algo:MxM}. -\marginnote{TODO: Оформление алгоритмов точно надо обсудить, потому что я в этом мало понимаю.} -Его работу можно описать следующим образом: для каждой строки в первой матрице и для каждого столбца в второй матрице найти сумму произведений соответствующих элементов. -Данная сумма будет значением соответствующей ячейки результирующей матрицы. - -\begin{algorithm}{Наивное умножение матриц}{MxM} - \begin{pseudo}[] - \kw{function} \pr{MatrixMult}(M_1, M_2, G = (S, \oplus, \otimes)) \\+ - $M_3 = $ пустая матрица размера $n \times n$ \\ - \kw{for} $i \in [0 \rng n - 1]$ \\+ - \kw{for} $j \in [0 \rng n - 1]$ \\+ - \kw{for} $k \in [0 \rng n - 1]$ \\+ - $M_3[i, j] = M_3[i, j] \oplus (M_1[i, k] \otimes M_2[k, j])$ \\--- - \kw{return} $M_3$ - \end{pseudo} -\end{algorithm} - -Сложность наивного произведения двух матриц составляет $O(n^3)$ из-за тройного вложенного цикла, где каждый уровень вложенности привносит $n$ итераций. -Но можно ли улучшить этот алгоритм? -Первый положительный ответ был опубликовал Ф. Штрассен в 1969 году~\sidecite{Strassen1969}. -Сложность предложенного им алгоритма~--- $O(n^{\log_2 7}) \approx O(n^{2.81})$. -Основная идея~--- рекурсивное разбиение исходных матриц на блоки и вычисление их произведения с помощью только 7 умножений, а не 8. - -Рассмотрим алгоритм Штрассена более подробно. -Пусть $A$ и $B$~--- две квадратные матрицы размера $2^n \times 2^n$ над кольцом $R=(S, \oplus, \otimes)$. -Если размер умножаемых матриц не является натуральной степенью двойки, то дополняем исходные матрицы дополнительными нулевыми строками и столбцами. -Наша задача найти матрицу $C = A \cdot B$. - -Разделим матрицы $A, B$ и $C$ на четыре равные по размеру блока. -\[ - A = - \begin{pmatrix} - A_{1,1} & A_{1,2} \\ - A_{2,1} & A_{2,2} - \end{pmatrix}, - \quad - B = - \begin{pmatrix} - B_{1,1} & B_{1,2} \\ - B_{2,1} & B_{2,2} - \end{pmatrix}, - \quad - C = - \begin{pmatrix} - C_{1,1} & C_{1,2} \\ - C_{2,1} & C_{2,2} - \end{pmatrix} -\] - -По определению произведения матриц выполняются следующие равенства. -\marginnote{TODO: Вообще можно попробовать раскидать на 2 столбца} -\begin{align*} - C_{1, 1} & = A_{1, 1} \cdot B_{1, 1} + A_{1, 2} \cdot B_{2, 1} \\ - C_{1, 2} & = A_{1, 1} \cdot B_{1, 2} + A_{1, 2} \cdot B_{2, 2} \\ - C_{2, 1} & = A_{2, 1} \cdot B_{1, 1} + A_{2, 2} \cdot B_{2, 1} \\ - C_{2, 2} & = A_{2, 1} \cdot B_{1, 2} + A_{2, 2} \cdot B_{2, 2} -\end{align*} - -Данная процедура не даёт нам ничего нового с точки зрения вычислительной сложности. -Но мы можем двинуться дальше и определить следующие элементы. -\begin{align*} - P_1 & \equiv (A_{1, 1} + A_{2, 2}) \cdot (B_{1, 1} + B_{2, 2}) \\ - P_2 & \equiv (A_{2, 1} + A_{2, 2}) \cdot B_{1, 1} \\ - P_3 & \equiv A_{1, 1} \cdot (B_{1, 2} - B_{2, 2}) \\ - P_4 & \equiv A_{2, 2} \cdot (B_{2, 1} - B_{1, 1}) \\ - P_5 & \equiv (A_{1, 1} + A_{1, 2}) \cdot B_{2, 2} \\ - P_6 & \equiv (A_{2, 1} - A_{1, 1}) \cdot (B_{1, 1} + B_{1, 2}) \\ - P_7 & \equiv (A_{1, 2} - A_{2, 2}) \cdot (B_{2, 1} + B_{2, 2}) -\end{align*} - -Используя эти элементы мы можем выразить блоки результирующей матрицы следующим образом. -\begin{align*} - C_{1, 1} & = P_1 + P_4 - P_5 + P_7 \\ - C_{1, 2} & = P_3 + P_5 \\ - C_{2, 1} & = P_2 + P_4 \\ - C_{2, 2} & = P_1 - P_2 + P_3 + P_6 -\end{align*} - -При таком способе вычисления мы получаем на одно умножение подматриц меньше, чем при наивном подходе. -Это и приводит, в конечном итоге, к улучшению сложности всего алгоритма, который основывается на рекурсивном повторении проделанной выше процедуры. - -\marginnote{TODO: здесь \textbackslash{}sidecite не влезает} -Впоследствии сложность постепенно понижалась в ряде работ, таких как~\cite{Pan1978,BiniCapoRoma1979,Schonhage1981,CoppWino1982,CoppWino1990}. -Было введено специальное обозначение для показателя степени в данной оценке: $\omega$. -То есть сложность умножения матриц~--- это $O(n^\omega)$, и задача сводится к уменьшению значения $\omega$. -В настоящее время работа над уменьшением показателя степени продолжается и сейчас уже предложены решения с $\omega < 2.373$% -\sidenote{ - В данной области достаточно регулярно появляются новые результаты, дающие сравнительно небольшие, в терминах абсолютных величин, изменения. - Так, в 2021 была представлена работа, улучшающая значение $\omega$ в пятом знаке после запятой~\cite{alman2020refined}. - Несмотря на кажущуюся несерьёзность результата, подобные работы имеют большое теоретическое значение, так как улучшают наше понимание исходной задачи и её свойств.}% -. - -Всё тем же Ф. Штрассеном ещё в 1969 году была выдвинута гипотеза о том, что для достаточно больших $n$ существует алгоритм, который для любого сколь угодно маленького наперёд заданного $\varepsilon$ перемножает матрицы за $O(n^{2+\varepsilon})$. -На текущий момент ни доказательства, ни опровержения этой гипотезы не предъявлено. - -Важной особенностью указанного выше направления улучшения алгоритмов является то, что оно допускает использования (и даже основывается на использовании) более богатых алгебраических структур, чем требуется для определения умножения двух матриц. -Так, уже алгоритм Штрасеена использует операцию вычитания, что приводит к необходимости иметь обратные элементы по сложению, а значит определять матрицы над кольцом. -Хотя для исходного определения (\ref{def:MxM}) достаточно более бедной структуры. -При этом, часто, структуры, возникающие в прикладных задачах кольцами не являются. -\marginnote{TODO: Не кажется ли что текста на полях слишком много и его можно прямо в главу вписать?} -Примерами могут служить тропическое (или $\{min, +\}$) полукольцо, играющее ключевую роль в тропической математике, или булево ($\{\lor, \land\}$) полукольцо, возникающее, например, при работе с отношениями% -\sidenote{ - Вообще говоря, в некоторых прикладных задачах возникают структуры, не являющиеся даже полукольцом. - Предположим, что есть три различных множества $S_1$, $S_2$ и $S_3$ и две двухместные функции $f: S_1 \times S_2 \to S_3$ и $g: S_3 \times S_3 \to S_3$. - Этого достаточно, чтобы определить произведение двух матриц $M_1$ и $M_2$, построенных из элементов множеств $S_1$ и $S_2$ соответственно. - Результирующая матрица будет состоять из элементов $S_3$. - Как видно, функции не являются бинарными операциями в смысле нашего определения. - Несмотря на кажущуюся экзотичность, подобные структуры возникают на практике при работе с графами и учитываются, например, в стандарте GraphBLAS (\url{https://graphblas.github.io/}), где, кстати, называются полукольцами, что выглядит не вполне корректно.}% -. -Значит, описанные выше решения не применимы и вопрос о существовании алгоритма с менее чем кубической сложностью снова актуален. - -В попытках ответить на этот вопрос появились так называемые комбинаторные алгоритмы умножения матриц% -\sidenote{ - В противовес описанным выше, не являющимся комбинаторными. - Стоит отметить, что строгое определение комбинаторных алгоритмов отсутствует, хотя этот термин и получил широкое употребление. - В частности, Н.~Бансал (Nikhil Bansal) и Р.~Уильямс (Ryan Williams) в работе~\cite{5438580} дают определение комбинаторного алгоритма, но тут же замечают следующее: \enquote{We would like to give a definition of \enquote{combinatorial algorithm}, but this appears elusive. Although the term has been used in many of the cited references, nothing in the literature resembles a definition. For the purposes of this paper, let us think of a \enquote{combinatorial algorithm} simply as one that does not call an oracle for ring matrix multiplication.}. - Ещё один вариант определения и его обсуждение можно найти в~\cite{das2018lower}.}% -. -Классический результат в данной области~--- это алгоритм четырёх русских, предложенный В. Л. Арлазаровым, Е. А. Диницем, М. А. Кронродом и И. А. Фараджевым в 1970 году~\cite{ArlDinKro70}, позволяющий перемножить матрицы над конечным полукольцом за $O(n^3/\log n)$. -Лучшим результатом% -\sidenote{ -В работе~\cite{das2018lower} предложен алгоритм со сложностью $\Omega(n^{7/3}/2^{O(\sqrt{\log n})})$, однако авторы утверждают, что сами не уверены в комбинаторности предложенного решения. -По-видимому, полученные результаты ещё должны быть проверены сообществом.} -в настоящее время является алгоритм со сложностью% -\sidenote{Нотация $\hat{O}$ скрывает $poly(\log\log)$ коэффициенты.} $\hat{O}(n^3/\log^4 n)$~\cite{10.1007/978-3-662-47672-7_89}. - -Как видим, особенности алгебраических структур накладывают серьёзные ограничения на возможности конструирования алгоритмов. -Отметим, что, хотя, в указанных случаях и предлагаются решения лучшие, чем наивное кубическое, они обладают принципиально разной асимптотической сложностью. -В первом случае сложность оценивается полиномом, степень которого меньше третьей. -Такие решения принято называть \emph{истинно субкубическими} (truly subcubic). -В то время как в случае комбинаторных алгоритмов степень полинома остается прежней, третьей, хотя сложность и уменьшается на логарифмический фактор. -Такие решения принято называть \emph{слегка субкубическими} (mildly subcubic). -Естественный вопрос о существовании истинно субкубического алгоритма перемножения матриц над полукольцами (или же комбинаторного перемножения матриц) всё ещё не решён% -\sidenote{Один из кандидатов~--- работа~\cite{das2018lower}, однако на текущий момент предложенное в ней решение требует проверки.}. - -%Заметим, что скалярная операция~--- это частный случай произвеления Кронекера: достаточно превратить элемент носителя полугруппы в матрицу размера $1\times 1$. - -%\section{Вопросы и задачи} -%\begin{enumerate} -% \item Привидите примеры некоммутативных операций. -% \item Привидите примеры ситуаций, когда наличие у бинарных операций каких-либо дополнитльных свойств (ассоциативности, коммутативности), позволяет строить более эффективные алгоритмы, чем в общем случае. -%\end{enumerate} +%% FIXME: Исправить раздел +% \section{Теоретическая сложность умножения матриц} + +% В рамках такого раздела теории сложности, как мелкозернистая сложность (fine-grained complexity) задача умножения двух матриц оказалась достаточно важной, так как через вычислительную сложность этой задачи можно оценить сложность большого класса различных задач. +% С примерами таких задач можно ознакомиться в работе~\sidecite{Williams:2010:SEP:1917827.1918339}. Поэтому рассмотрим алгоритмы нахождения произведения двух матриц более подробно. +% Далее для простоты мы будем предполагать, что перемножаются две квадратные матрицы одинакового размера $n \times n$. + +% Для начала построим наивный алгоритм, сконструированный на основе определения произведения матриц. +% Такой алгоритм представлен на листинге~\ref{algo:MxM}. +% \marginnote{TODO: Оформление алгоритмов точно надо обсудить, потому что я в этом мало понимаю.} +% Его работу можно описать следующим образом: для каждой строки в первой матрице и для каждого столбца в второй матрице найти сумму произведений соответствующих элементов. +% Данная сумма будет значением соответствующей ячейки результирующей матрицы. + +% \begin{algorithm}{Наивное умножение матриц}{MxM} +% \begin{pseudo}[] +% \kw{function} \pr{MatrixMult}(M_1, M_2, G = (S, \oplus, \otimes)) \\+ +% $M_3 = $ пустая матрица размера $n \times n$ \\ +% \kw{for} $i \in [0 \rng n - 1]$ \\+ +% \kw{for} $j \in [0 \rng n - 1]$ \\+ +% \kw{for} $k \in [0 \rng n - 1]$ \\+ +% $M_3[i, j] = M_3[i, j] \oplus (M_1[i, k] \otimes M_2[k, j])$ \\--- +% \kw{return} $M_3$ +% \end{pseudo} +% \end{algorithm} + +% Сложность наивного произведения двух матриц составляет $O(n^3)$ из-за тройного вложенного цикла, где каждый уровень вложенности привносит $n$ итераций. +% Но можно ли улучшить этот алгоритм? +% Первый положительный ответ был опубликовал Ф. Штрассен в 1969 году~\sidecite{Strassen1969}. +% Сложность предложенного им алгоритма~--- $O(n^{\log_2 7}) \approx O(n^{2.81})$. +% Основная идея~--- рекурсивное разбиение исходных матриц на блоки и вычисление их произведения с помощью только 7 умножений, а не 8. + +% Рассмотрим алгоритм Штрассена более подробно. +% Пусть $A$ и $B$~--- две квадратные матрицы размера $2^n \times 2^n$ над кольцом $R=(S, \oplus, \otimes)$. +% Если размер умножаемых матриц не является натуральной степенью двойки, то дополняем исходные матрицы дополнительными нулевыми строками и столбцами. +% Наша задача найти матрицу $C = A \cdot B$. + +% Разделим матрицы $A, B$ и $C$ на четыре равные по размеру блока. +% \[ +% A = +% \begin{pmatrix} +% A_{1,1} & A_{1,2} \\ +% A_{2,1} & A_{2,2} +% \end{pmatrix}, +% \quad +% B = +% \begin{pmatrix} +% B_{1,1} & B_{1,2} \\ +% B_{2,1} & B_{2,2} +% \end{pmatrix}, +% \quad +% C = +% \begin{pmatrix} +% C_{1,1} & C_{1,2} \\ +% C_{2,1} & C_{2,2} +% \end{pmatrix} +% \] + +% По определению произведения матриц выполняются следующие равенства. +% \marginnote{TODO: Вообще можно попробовать раскидать на 2 столбца} +% \begin{align*} +% C_{1, 1} & = A_{1, 1} \cdot B_{1, 1} + A_{1, 2} \cdot B_{2, 1} \\ +% C_{1, 2} & = A_{1, 1} \cdot B_{1, 2} + A_{1, 2} \cdot B_{2, 2} \\ +% C_{2, 1} & = A_{2, 1} \cdot B_{1, 1} + A_{2, 2} \cdot B_{2, 1} \\ +% C_{2, 2} & = A_{2, 1} \cdot B_{1, 2} + A_{2, 2} \cdot B_{2, 2} +% \end{align*} + +% Данная процедура не даёт нам ничего нового с точки зрения вычислительной сложности. +% Но мы можем двинуться дальше и определить следующие элементы. +% \begin{align*} +% P_1 & \equiv (A_{1, 1} + A_{2, 2}) \cdot (B_{1, 1} + B_{2, 2}) \\ +% P_2 & \equiv (A_{2, 1} + A_{2, 2}) \cdot B_{1, 1} \\ +% P_3 & \equiv A_{1, 1} \cdot (B_{1, 2} - B_{2, 2}) \\ +% P_4 & \equiv A_{2, 2} \cdot (B_{2, 1} - B_{1, 1}) \\ +% P_5 & \equiv (A_{1, 1} + A_{1, 2}) \cdot B_{2, 2} \\ +% P_6 & \equiv (A_{2, 1} - A_{1, 1}) \cdot (B_{1, 1} + B_{1, 2}) \\ +% P_7 & \equiv (A_{1, 2} - A_{2, 2}) \cdot (B_{2, 1} + B_{2, 2}) +% \end{align*} + +% Используя эти элементы мы можем выразить блоки результирующей матрицы следующим образом. +% \begin{align*} +% C_{1, 1} & = P_1 + P_4 - P_5 + P_7 \\ +% C_{1, 2} & = P_3 + P_5 \\ +% C_{2, 1} & = P_2 + P_4 \\ +% C_{2, 2} & = P_1 - P_2 + P_3 + P_6 +% \end{align*} + +% При таком способе вычисления мы получаем на одно умножение подматриц меньше, чем при наивном подходе. +% Это и приводит, в конечном итоге, к улучшению сложности всего алгоритма, который основывается на рекурсивном повторении проделанной выше процедуры. + +% \marginnote{TODO: здесь \textbackslash{}sidecite не влезает} +% Впоследствии сложность постепенно понижалась в ряде работ, таких как~\cite{Pan1978,BiniCapoRoma1979,Schonhage1981,CoppWino1982,CoppWino1990}. +% Было введено специальное обозначение для показателя степени в данной оценке: $\omega$. +% То есть сложность умножения матриц~--- это $O(n^\omega)$, и задача сводится к уменьшению значения $\omega$. +% В настоящее время работа над уменьшением показателя степени продолжается и сейчас уже предложены решения с $\omega < 2.373$% +% \sidenote{ +% В данной области достаточно регулярно появляются новые результаты, дающие сравнительно небольшие, в терминах абсолютных величин, изменения. +% Так, в 2021 была представлена работа, улучшающая значение $\omega$ в пятом знаке после запятой~\cite{alman2020refined}. +% Несмотря на кажущуюся несерьёзность результата, подобные работы имеют большое теоретическое значение, так как улучшают наше понимание исходной задачи и её свойств.}% +% . + +% Всё тем же Ф. Штрассеном ещё в 1969 году была выдвинута гипотеза о том, что для достаточно больших $n$ существует алгоритм, который для любого сколь угодно маленького наперёд заданного $\varepsilon$ перемножает матрицы за $O(n^{2+\varepsilon})$. +% На текущий момент ни доказательства, ни опровержения этой гипотезы не предъявлено. + +% Важной особенностью указанного выше направления улучшения алгоритмов является то, что оно допускает использования (и даже основывается на использовании) более богатых алгебраических структур, чем требуется для определения умножения двух матриц. +% Так, уже алгоритм Штрасеена использует операцию вычитания, что приводит к необходимости иметь обратные элементы по сложению, а значит определять матрицы над кольцом. +% Хотя для исходного определения (\ref{def:MxM}) достаточно более бедной структуры. +% При этом, часто, структуры, возникающие в прикладных задачах кольцами не являются. +% \marginnote{TODO: Не кажется ли что текста на полях слишком много и его можно прямо в главу вписать?} +% Примерами могут служить тропическое (или $\{min, +\}$) полукольцо, играющее ключевую роль в тропической математике, или булево ($\{\lor, \land\}$) полукольцо, возникающее, например, при работе с отношениями% +% \sidenote{ +% Вообще говоря, в некоторых прикладных задачах возникают структуры, не являющиеся даже полукольцом. +% Предположим, что есть три различных множества $S_1$, $S_2$ и $S_3$ и две двухместные функции $f: S_1 \times S_2 \to S_3$ и $g: S_3 \times S_3 \to S_3$. +% Этого достаточно, чтобы определить произведение двух матриц $M_1$ и $M_2$, построенных из элементов множеств $S_1$ и $S_2$ соответственно. +% Результирующая матрица будет состоять из элементов $S_3$. +% Как видно, функции не являются бинарными операциями в смысле нашего определения. +% Несмотря на кажущуюся экзотичность, подобные структуры возникают на практике при работе с графами и учитываются, например, в стандарте GraphBLAS (\url{https://graphblas.github.io/}), где, кстати, называются полукольцами, что выглядит не вполне корректно.}% +% . +% Значит, описанные выше решения не применимы и вопрос о существовании алгоритма с менее чем кубической сложностью снова актуален. + +% В попытках ответить на этот вопрос появились так называемые комбинаторные алгоритмы умножения матриц% +% \sidenote{ +% В противовес описанным выше, не являющимся комбинаторными. +% Стоит отметить, что строгое определение комбинаторных алгоритмов отсутствует, хотя этот термин и получил широкое употребление. +% В частности, Н.~Бансал (Nikhil Bansal) и Р.~Уильямс (Ryan Williams) в работе~\cite{5438580} дают определение комбинаторного алгоритма, но тут же замечают следующее: \enquote{We would like to give a definition of \enquote{combinatorial algorithm}, but this appears elusive. Although the term has been used in many of the cited references, nothing in the literature resembles a definition. For the purposes of this paper, let us think of a \enquote{combinatorial algorithm} simply as one that does not call an oracle for ring matrix multiplication.}. +% Ещё один вариант определения и его обсуждение можно найти в~\cite{das2018lower}.}% +% . +% Классический результат в данной области~--- это алгоритм четырёх русских, предложенный В. Л. Арлазаровым, Е. А. Диницем, М. А. Кронродом и И. А. Фараджевым в 1970 году~\cite{ArlDinKro70}, позволяющий перемножить матрицы над конечным полукольцом за $O(n^3/\log n)$. +% Лучшим результатом% +% \sidenote{ +% В работе~\cite{das2018lower} предложен алгоритм со сложностью $\Omega(n^{7/3}/2^{O(\sqrt{\log n})})$, однако авторы утверждают, что сами не уверены в комбинаторности предложенного решения. +% По-видимому, полученные результаты ещё должны быть проверены сообществом.} +% в настоящее время является алгоритм со сложностью% +% \sidenote{Нотация $\hat{O}$ скрывает $poly(\log\log)$ коэффициенты.} $\hat{O}(n^3/\log^4 n)$~\cite{10.1007/978-3-662-47672-7_89}. + +% Как видим, особенности алгебраических структур накладывают серьёзные ограничения на возможности конструирования алгоритмов. +% Отметим, что, хотя, в указанных случаях и предлагаются решения лучшие, чем наивное кубическое, они обладают принципиально разной асимптотической сложностью. +% В первом случае сложность оценивается полиномом, степень которого меньше третьей. +% Такие решения принято называть \emph{истинно субкубическими} (truly subcubic). +% В то время как в случае комбинаторных алгоритмов степень полинома остается прежней, третьей, хотя сложность и уменьшается на логарифмический фактор. +% Такие решения принято называть \emph{слегка субкубическими} (mildly subcubic). +% Естественный вопрос о существовании истинно субкубического алгоритма перемножения матриц над полукольцами (или же комбинаторного перемножения матриц) всё ещё не решён% +% \sidenote{Один из кандидатов~--- работа~\cite{das2018lower}, однако на текущий момент предложенное в ней решение требует проверки.}. + +% %Заметим, что скалярная операция~--- это частный случай произвеления Кронекера: достаточно превратить элемент носителя полугруппы в матрицу размера $1\times 1$. + +% %\section{Вопросы и задачи} +% %\begin{enumerate} +% % \item Привидите примеры некоммутативных операций. +% % \item Привидите примеры ситуаций, когда наличие у бинарных операций каких-либо дополнитльных свойств (ассоциативности, коммутативности), позволяет строить более эффективные алгоритмы, чем в общем случае. +% %\end{enumerate} diff --git a/tex/Matrix-based_CFPQ.tex b/tex/Matrix-based_CFPQ.tex index 6cab06b..d6a2698 100644 --- a/tex/Matrix-based_CFPQ.tex +++ b/tex/Matrix-based_CFPQ.tex @@ -188,38 +188,39 @@ \end{example} -\subsection{Расширение алгоритма для конъюнктивных грамматик} - -Матричный алгоритм для конъюнктивных грамматик отличается от алгоритма~\ref{alg:graphParse} для контекстно-свободных грамматик только операцией умножения матриц, в остальном алгоритм остается без изменений. Определим операцию умножения матриц. -\begin{definition} - Пусть $M_1$ и $M_2$ матрицы размера $n$. Определим операцию $\circ$ следующим образом: - \[M_1 \circ M_2 = M_3,\] - \[M_3 [i,j] = \{A \mid \exists (A \rightarrow B_1 C_1 \& \ldots \& B_m C_m) \in P, (B_k , C_k) \in d[i,j] \forall k = 1,\ldots,m\}\], - где \[d[i,j] = \bigcup_{k = 1}^{n} M_1 [i,k] \times M_2 [k,j].\] -\end{definition} - -Важно заметить, что алгоритм для конъюнктивных грамматик, в отличие от алгоритма для контекстно-свободных грамматик, дает лишь верхнюю оценку ответа. То есть все нетерминалы, которые должны быть в ячейках матрицы результата, содержатся там, но вместе с ними содержатся и лишние нетерминалы. Рассмотрим пример, иллюстрирующий появление лишних нетерминалов. - -\begin{example} - Грамматика $G$: - \begin{align*} - S &\to AB \& DC & C &\to c \\ - A &\to a & D &\to DC \mid b\\ - B &\to BC \mid b - \end{align*} - Очевидно, что грамматика $G$ задает язык из одного слова $L(G) = \{abc\} = \{abc^*\} \cap \{a^* bc\}$. - - Пусть есть граф $\mathcal{G}$: - \begin{center} - \input{figures/multi/graph0.tex} - \end{center} - Применяя алгоритм, получим, что существует путь из вершины 0 в вершину 4, выводимый из нетерминала $S$. Однако очевидно, что в графе такого пути нет. - Такое поведение алгоритма наблюдается из-за того, что существует путь ``abcc'', соответствующий $L(AB) = \{abc^*\}$ и путь ``aabc'', соответствующий $L(DC) = \{a^{*}bc\}$, но они различны. Однако алгоритм не может это проверить, так как оперирует понятием достижимости между вершинами, а не наличием различных путей. Более того, в общем случае для конъюнктивных грамматик такую проверку реалиховать нельзя. Поэтому для классической семантики достидимости с ограничениями в терминах конъюнктивных грамматик результат работы алгоритма является оценкой сверху. - - Существует альтернативная семантика, когда мы трактуем конъюнкцию в правой части правил как конъюнкцию в Datalog (подробнее о Datalog в параграфе~\ref{Subsection Datalog}). Т.е если есть правило $S \to AB \& DC$, то должен быть путь принадлежащий языку $L(AB)$ и путь принадлежащий языку $L(DC)$. В такой семантике алгоритм дает точный ответ. -\end{example} - -Подробнее алгоритм описан в статье Рустама Азимова и Семёна Григорьева~\cite{565CECD7E8F5C6063935B41DB41797AA37D53B04}. Стоит также отметить, что обобщения данного алгоритма для булевых грамматик не существует, хотя и существует частное решение для случая, когда граф не содержит циклов (является DAG-ом), предложенное Екатериной Шеметовой~\cite{Shemetova2019}. +%% FIXME: Исправить подраздел +% \subsection{Расширение алгоритма для конъюнктивных грамматик} + +% Матричный алгоритм для конъюнктивных грамматик отличается от алгоритма~\ref{alg:graphParse} для контекстно-свободных грамматик только операцией умножения матриц, в остальном алгоритм остается без изменений. Определим операцию умножения матриц. +% \begin{definition} +% Пусть $M_1$ и $M_2$ матрицы размера $n$. Определим операцию $\circ$ следующим образом: +% \[M_1 \circ M_2 = M_3,\] +% \[M_3 [i,j] = \{A \mid \exists (A \rightarrow B_1 C_1 \& \ldots \& B_m C_m) \in P, (B_k , C_k) \in d[i,j] \forall k = 1,\ldots,m\}\], +% где \[d[i,j] = \bigcup_{k = 1}^{n} M_1 [i,k] \times M_2 [k,j].\] +% \end{definition} + +% Важно заметить, что алгоритм для конъюнктивных грамматик, в отличие от алгоритма для контекстно-свободных грамматик, дает лишь верхнюю оценку ответа. То есть все нетерминалы, которые должны быть в ячейках матрицы результата, содержатся там, но вместе с ними содержатся и лишние нетерминалы. Рассмотрим пример, иллюстрирующий появление лишних нетерминалов. + +% \begin{example} +% Грамматика $G$: +% \begin{align*} +% S &\to AB \& DC & C &\to c \\ +% A &\to a & D &\to DC \mid b\\ +% B &\to BC \mid b +% \end{align*} +% Очевидно, что грамматика $G$ задает язык из одного слова $L(G) = \{abc\} = \{abc^*\} \cap \{a^* bc\}$. + +% Пусть есть граф $\mathcal{G}$: +% \begin{center} +% \input{figures/multi/graph0.tex} +% \end{center} +% Применяя алгоритм, получим, что существует путь из вершины 0 в вершину 4, выводимый из нетерминала $S$. Однако очевидно, что в графе такого пути нет. +% Такое поведение алгоритма наблюдается из-за того, что существует путь ``abcc'', соответствующий $L(AB) = \{abc^*\}$ и путь ``aabc'', соответствующий $L(DC) = \{a^{*}bc\}$, но они различны. Однако алгоритм не может это проверить, так как оперирует понятием достижимости между вершинами, а не наличием различных путей. Более того, в общем случае для конъюнктивных грамматик такую проверку реалиховать нельзя. Поэтому для классической семантики достидимости с ограничениями в терминах конъюнктивных грамматик результат работы алгоритма является оценкой сверху. + +% Существует альтернативная семантика, когда мы трактуем конъюнкцию в правой части правил как конъюнкцию в Datalog (подробнее о Datalog в параграфе~\ref{Subsection Datalog}). Т.е если есть правило $S \to AB \& DC$, то должен быть путь принадлежащий языку $L(AB)$ и путь принадлежащий языку $L(DC)$. В такой семантике алгоритм дает точный ответ. +% \end{example} + +% Подробнее алгоритм описан в статье Рустама Азимова и Семёна Григорьева~\cite{565CECD7E8F5C6063935B41DB41797AA37D53B04}. Стоит также отметить, что обобщения данного алгоритма для булевых грамматик не существует, хотя и существует частное решение для случая, когда граф не содержит циклов (является DAG-ом), предложенное Екатериной Шеметовой~\cite{Shemetova2019}. \section{Особенности реализации} From c559dddcb334c78491f8e81c062b598cbb3a5394 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Wed, 19 Jun 2024 22:15:59 +0300 Subject: [PATCH 27/29] Name TikZ externalized PDFs according to chapter --- tex/Context-Free_Languages.tex | 1 + tex/FormalLanguageConstrainedReachabilityLectureNotes.tex | 5 ----- tex/FormalLanguageTheoryIntro.tex | 1 + tex/GraphTheoryIntro.tex | 1 + tex/Introduction.tex | 1 + tex/LinearAlgebra.tex | 1 + tex/RegularLanguages.tex | 1 + 7 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tex/Context-Free_Languages.tex b/tex/Context-Free_Languages.tex index 0581e04..c629fd4 100644 --- a/tex/Context-Free_Languages.tex +++ b/tex/Context-Free_Languages.tex @@ -1,6 +1,7 @@ \setchapterpreamble[u]{\margintoc} \chapter{Контекстно-свободные языки и грамматики} \label{CFG} +\tikzsetfigurename{CFG_} Из всего многообразия нас будут интересовать прежде всего контекстно-свободные грамматики. diff --git a/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex b/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex index 453f00e..6ce1444 100644 --- a/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex +++ b/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex @@ -40,11 +40,6 @@ \setchapterstyle{kao} \input{Introduction} - -\pagelayout{wide} % No margins -\addpart{Необходимые вводные} -\pagelayout{margin} % Restore margins - \input{LinearAlgebra} \input{GraphTheoryIntro} \input{FormalLanguageTheoryIntro} diff --git a/tex/FormalLanguageTheoryIntro.tex b/tex/FormalLanguageTheoryIntro.tex index 5e1c829..b93d7f0 100644 --- a/tex/FormalLanguageTheoryIntro.tex +++ b/tex/FormalLanguageTheoryIntro.tex @@ -1,6 +1,7 @@ \setchapterpreamble[u]{\margintoc} \chapter{Общие сведения теории формальных языков} \label{chpt:FormalLanguageTheoryIntro} +\tikzsetfigurename{FormalLanguageTheoryIntro_} В данной главе мы рассмотрим основные понятия из теории формальных языков, которые пригодятся нам в дальнейшем изложении. Заметим, что мы рассмотрим лишь те результаты теории формальных языков,которые будут необходимы нам для дальнейшего изложения. diff --git a/tex/GraphTheoryIntro.tex b/tex/GraphTheoryIntro.tex index 7198172..c36fccf 100644 --- a/tex/GraphTheoryIntro.tex +++ b/tex/GraphTheoryIntro.tex @@ -1,6 +1,7 @@ \setchapterpreamble[u]{\margintoc} \chapter{Некоторые сведения из теории графов} \label{chpt:GraphTheoryIntro} +\tikzsetfigurename{GraphTheoryIntro_} В данном разделе мы дадим определения базовым понятиям из теории графов, рассмотрим несколько классических задач из области анализа графов и алгоритмы их решения. Кроме этого, поговорим о связи между линейной алгеброй и некоторыми задачами анализа графов. diff --git a/tex/Introduction.tex b/tex/Introduction.tex index a09893b..970f9c5 100644 --- a/tex/Introduction.tex +++ b/tex/Introduction.tex @@ -1,4 +1,5 @@ \addchap{Введение} +\tikzsetfigurename{Introduction_} Теория формальных языков находит применение не только в ставших уже классическими задачах синтаксического анализа кода (языков программирования, искусственных языков) и естественных языков, но и в других областях, таких как статический анализ кода, графовые базы данных, биоинформатика, машинное обучение. diff --git a/tex/LinearAlgebra.tex b/tex/LinearAlgebra.tex index 6ddf08a..bd44a90 100644 --- a/tex/LinearAlgebra.tex +++ b/tex/LinearAlgebra.tex @@ -1,6 +1,7 @@ \setchapterpreamble[u]{\margintoc} \chapter{Некоторые понятия линейной алгебры} \label{chpt:LinAlIntro} +\tikzsetfigurename{LinearAlgebra_} При изложении ряда алгоритмов будут активно использоваться некоторые понятия и инструменты линейной алгебры, такие как моноид, полукольцо или матрица. В данном разделе необходимые понятия будут определены и приведены некоторые примеры соответствующих конструкций. diff --git a/tex/RegularLanguages.tex b/tex/RegularLanguages.tex index de98dd7..572d324 100644 --- a/tex/RegularLanguages.tex +++ b/tex/RegularLanguages.tex @@ -1,5 +1,6 @@ \setchapterpreamble[u]{\margintoc} \chapter{Регулярные языки} +\tikzsetfigurename{RegularLanguages_} В данном разделе мы обсудим регулярные языки~--- класс, лежащий на самом нижнем уровне иерархии Хомского. Будут рассмотрены основные способы задания таких языков: \emph{регулярные выражения}, \emph{конечные автоматы}, \emph{лево(право)линейные грамматики}. From 7568b0aa0ba4d86a54461288cc614dbdba3fdb5f Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Wed, 19 Jun 2024 23:01:20 +0300 Subject: [PATCH 28/29] Add FLPQ chapter --- tex/FLPQ.tex | 123 +++++++++--------- ...ageConstrainedReachabilityLectureNotes.tex | 2 +- 2 files changed, 60 insertions(+), 65 deletions(-) diff --git a/tex/FLPQ.tex b/tex/FLPQ.tex index 22dfdda..01dfb8f 100644 --- a/tex/FLPQ.tex +++ b/tex/FLPQ.tex @@ -1,62 +1,64 @@ -\chapter[Пути с ограничениями в терминах формальных языков]{Задача о поиске путей с ограничениями в терминах формальных языков}\label{chpt:FLPQ} - - +\setchapterpreamble[u]{\margintoc} +\chapter[Пути с ограничениями в терминах формальных языков]{Задача о поиске путей с ограничениями в терминах формальных языков} +\label{chpt:FLPQ} +\tikzsetfigurename{FLPQ_} В данной главе сформулируем постановку задачи о поиске путей в графе с ограничениями. Также мы приведём несколько примеров областей, в которых применяются алгоритмы решения этой задачи. -\section{Постановка задачи } +\section{Постановка задачи} - -Пусть нам дан конечный ориентированный помеченный граф $\mathcal{G}=\langle V,E,L \rangle$. -Функция $\omega(\pi) = \omega((v_0, l_0, v_1),(v_1,l_1,v_2),\dots,(v_{n-1},l_{n-1},v_n)) = l_0 \cdot l_1 \cdot \ldots \cdot l_{n-1} $ строит слово по пути посредством конкатенации меток рёбер вдоль этого пути. -Очевидно, для пустого пути данная функция будет возвращать пустое слово, а для пути длины $n > 0$ --- непустое слово длины $n$. +Пусть нам дан конечный ориентированный помеченный граф $\mscrG = \langle V, E, L \rangle$. +Функция $\omega(\pi) = \omega((v_0, l_0, v_1), (v_1, l_1, v_2), \dots, (v_{n-1}, l_{n-1}, v_n)) = l_0 \cdot l_1 \cdot \dots \cdot l_{n-1}$ строит слово по пути посредством конкатенации меток рёбер вдоль этого пути. +Очевидно, для пустого пути данная функция будет возвращать пустое слово, а для пути длины $n > 0$~--- непустое слово длины $n$. Если теперь рассматривать задачу поиска путей, то окажется, что то множество путей, которое мы хотим найти, задаёт множество слов, то есть язык. А значит, критерий поиска мы можем сформулировать следующим образом: нас интересуют такие пути, что слова, составленные из меток вдоль них, принадлежат заданному языку. -\begin{definition} \label{def1} - \textit{Задача поиска путей с ограничениями в терминах формальных языков} заключается в поиске множества путей $\Pi = \{\pi \mid \omega(\pi) \in \mathcal{L}\}$. +\begin{definition}[Задача поиска путей с ограничениями в терминах формальных языков] + \label{def1} + \emph{Задача поиска путей с ограничениями в терминах формальных языков} заключается в поиске множества путей $\Pi = \{\pi \mid \omega(\pi) \in \mscrL\}$. \end{definition} -В задаче поиска путей мы можем накладывать дополнительные ограничения на путь (например, чтобы он был простым, кратчайшим или Эйлеровым~\cite{kupferman2016eulerian}), но это уже другая история. +В задаче поиска путей мы можем накладывать дополнительные ограничения на путь (например, чтобы он был простым, кратчайшим или Эйлеровым~\sidecite{kupferman2016eulerian}), но это уже другая история. Другим вариантом постановки задачи является задача достижимости. -\begin{definition} \label{def2} - \textit{Задача достижимости} заключается в поиске множества пар вершин, для которых найдется путь с началом и концом в этих вершинах, что слово, составленное из меток рёбер пути, будет принадлежать заданному языку. - $\Pi' = \{(v_{i}, v_{j}) \mid \exists v_{i} \pi v_{j}, \omega(\pi) \in \mathcal{L}\}$. - +\begin{definition}[Задача достижимости] + \label{def2} + \emph{Задача достижимости} заключается в поиске множества пар вершин, для которых найдется путь с началом и концом в этих вершинах, что слово, составленное из меток рёбер пути, будет принадлежать заданному языку + \[\Pi' = \{(v_{i}, v_{j}) \mid \exists v_{i} \pi v_{j}, \omega(\pi) \in \mscrL\}.\] \end{definition} -При этом, множество $\Pi$ может являться бесконечным, тогда как $\Pi'$ конечно, по причине конечности графа $\mathcal{G}$. +При этом, множество $\Pi$ может являться бесконечным, тогда как $\Pi'$ конечно, по причине конечности графа $\mscrG$. -Язык $\mathcal{L}$ может принадлежать разным классам и быть задан разными способами. Например, он может быть регулярным, контекстно-свободным, или многокомпонентным контекстно-свободным. +Язык $\mscrL$ может принадлежать разным классам и быть задан разными способами. +Например, он может быть регулярным, контекстно-свободным, или многокомпонентным контекстно-свободным. -Если $\mathcal{L}$ --- регулярный, $\mathcal{G}$ можно рассматривать как недетерминированный конечный автомат (НКА), в котором все вершины являются одновременно и стартовыми, и конечными. -Тогда задача поиска путей, в которой $\mathcal{L}$ --- регулярный, сводится к пересечению двух регулярных языков. +Если $\mscrL$~--- регулярный, $\mscrG$ можно рассматривать как недетерминированный конечный автомат (НКА), в котором все вершины являются одновременно и стартовыми, и конечными. +Тогда задача поиска путей, в которой $\mscrL$~--- регулярный, сводится к пересечению двух регулярных языков. -Более подробно мы рассмотрим случай, когда $\mathcal{L}$ --- контекстно-свободный язык. +Более подробно мы рассмотрим случай, когда $\mscrL$~--- контекстно-свободный язык. -Путь $G = \langle \Sigma, N, P \rangle$ --- контекстно-свободная грамматика. +Путь $G = \langle \Sigma, N, P \rangle$~--- контекстно-свободная грамматика. Будем считать, что $L \subseteq \Sigma$. Мы не фиксируем стартовый нетерминал в определении грамматики, поэтому, чтобы описать язык, задаваемый ей, нам необходимо отдельно зафиксировать стартовый нетерминал. -Таким образом, будем говорить, что $L(G,N_i) = \{ w \mid N_i \xRightarrow[G]{*} w \}$ --- это язык задаваемый грамматикой $G$ со стартовым нетерминалом $N_i$. +Таким образом, будем говорить, что $L(G,N_i) = \{ w \mid N_i \xRightarrow[G]{*} w \}$~--- это язык задаваемый грамматикой $G$ со стартовым нетерминалом $N_i$. \begin{example} Пример задачи поиска путей. - Дана грамматика $G$, задающая язык $\mathcal{L} = a^n b^n$: + Дана грамматика $G$, задающая язык $\mscrL = a^n b^n$: \begin{align*} - S &\to a b \\ - S &\to a S b + S & \to a b \\ + S & \to a S b \end{align*} - И дан граф $\mathcal{G}:$ + И дан граф $\mscrG$: \begin{center} - \input{figures/graph/graph0.tex} + \input{figures/graph/graph0.tex} \end{center} - Кратчайшими путями, принадлежащими множеству $\Pi = \{\pi \mid \omega(\pi) \in \mathcal{L}\}$, являются: + Кратчайшими путями, принадлежащими множеству $\Pi = \{\pi \mid \omega(\pi) \in \mscrL\}$, являются: \begin{center} \input{figures/flpq/path1.tex} @@ -71,40 +73,31 @@ \section{Постановка задачи } \section{О разрешимости задачи} -Задачи из определения \ref{def1} и \ref{def2} сводятся к построению пересечения языка $\mathcal{L}$ и языка, задаваемого путями графа, $R$. +Задачи из определения \ref{def1} и \ref{def2} сводятся к построению пересечения языка $\mscrL$ и языка, задаваемого путями графа, $R$. А мы для обсуждения разрешимости задачи рассмотрим более слабую постановку задачи: -\begin{definition} - Необходимо проверить, что существует хотя бы один такой путь $\pi$ для данного графа, для данного языка $\mathcal{L}$, что $\omega(\pi) \in \mathcal{L}$. - +\begin{definition}[TODO: Что ты?] + Необходимо проверить, что существует хотя бы один такой путь $\pi$ для данного графа, для данного языка $\mscrL$, что $\omega(\pi) \in \mscrL$. \end{definition} -Эта задача сводится к проверке пустоты пересечения языка $\mathcal{L}$ c $R$ --- регулярным языком, задаваемым графом. От класса языка $\mathcal{L}$ зависит её разрешимость: - +Эта задача сводится к проверке пустоты пересечения языка $\mscrL$ c $R$~--- регулярным языком, задаваемым графом. +От класса языка $\mscrL$ зависит её разрешимость: \begin{itemize} - \item Если $\mathcal{L}$ регулярный, то получаем задачу пересечения двух регулярных языков: - - $\mathcal{L} \cap R = R'$. - $R'$ --- также регулярный язык. - Проверка регулярного языка на пустоту --- разрешимая проблема. - - \item Если $\mathcal{L}$ контекстно-свободный, то получаем задачу - - $\mathcal{L} \cap R = CF$ --- контекстно-свободный. - Проверка контекстно-свободного языка на пустоту --- разрешимая проблема. - + \item Если $\mscrL$ регулярный, то получаем задачу пересечения двух регулярных языков: $\mscrL \cap R = R'$. + $R'$~--- также регулярный язык. + Проверка регулярного языка на пустоту~--- разрешимая проблема. + \item Если $\mscrL$ контекстно-свободный, то получаем задачу: $\mscrL \cap R = CF$~--- контекстно-свободный. + Проверка контекстно-свободного языка на пустоту~--- разрешимая проблема. \item Помимо иерархии Хомского существуют и другие классификации языков. - Так например, класс конъюнктивных (Conj) - языков~\cite{DBLP:journals/jalc/Okhotin01} - является строгим расширением контекстно-свободных языков и все так же позволяет полиномиальный синтаксический анализ. - - Пусть $\mathcal{L}$ --- конъюнктивный. При пересечении конъюнктивного и регулярного языков получается конъюнктивный ($\mathcal{L} \cap R = Conj$), а проблема проверки Conj на пустоту не разрешима~\cite{DBLP:journals/tcs/Okhotin03a}. + Так например, класс конъюнктивных (Conj) языков~\sidecite{DBLP:journals/jalc/Okhotin01}является строгим расширением контекстно-свободных языков и все так же позволяет полиномиальный синтаксический анализ. - \item Ещё один класс языков из альтернативной иерархии, не сравнимой с Иерархией Хомского, --- MCFG (multiple context-free grammars)~\cite{SEKI1991191}. - Как его частный случай --- TAG (tree adjoining grammar)~\cite{Joshi1997}. - - Если $\mathcal{L}$ принадлежит классу MCFG, то $\mathcal{L} \cap R$ также принадлежит MCFG. Проблема проверки пустоты MCFG разрешима~\cite{SEKI1991191}. + Пусть $\mscrL$~--- конъюнктивный. + При пересечении конъюнктивного и регулярного языков получается конъюнктивный ($\mscrL \cap R = Conj$), а проблема проверки Conj на пустоту не разрешима~\sidecite{DBLP:journals/tcs/Okhotin03a}. + \item Ещё один класс языков из альтернативной иерархии, не сравнимой с Иерархией Хомского,~--- MCFG (multiple context-free grammars)~\sidecite{SEKI1991191}. + Как его частный случай~--- TAG (tree adjoining grammar)~\sidecite{Joshi1997}. + Если $\mscrL$ принадлежит классу MCFG, то $\mscrL \cap R$ также принадлежит MCFG. + Проблема проверки пустоты MCFG разрешима~\sidecite{SEKI1991191}. \end{itemize} Существует ещё много других классификаций языков, но поиск универсальной иерархии до сих пор продолжается. @@ -113,18 +106,20 @@ \section{О разрешимости задачи} \section{Области применения} -Поиск путей с ограничениями в виде формальных языков широко применяется в различных областях. Ниже даны ключевые работы по применению поиска путей с контекстно-свободными ограничениями и ссылки на них для более детального ознакомления. - +Поиск путей с ограничениями в виде формальных языков широко применяется в различных областях. +Ниже даны ключевые работы по применению поиска путей с контекстно-свободными ограничениями и ссылки на них для более детального ознакомления. \begin{itemize} \item Межпроцедурный Статанализ кода. - Идея начала активно разрабатываться Томасом Репсом~\cite{Reps}. Далее последовал ряд, в том числе инженерных работ, применяющих достижимость с контекстно-свободными ограничениями для анализа указателей, анализа алиасов и других прикладных задач~\cite{LabelFlowCFLReachability,specificationCFLReachability,Zheng}. - \item Графовые БД. Впервые задача сформулирована Михалисом Яннакакисом~\cite{Yannakakis}. Запросы с контекстно-свободными ограничениями нашли своё применение различных областях. - \begin{itemize} - \item Социальные сети~\cite{Hellings2015PathRF}. - \item RDF обработка~\cite{10.1007/978-3-319-46523-4_38}. - \item Биоинформатика~\cite{cfpqBio}. - \end{itemize} - + Идея начала активно разрабатываться Томасом Репсом~\sidecite{Reps}. + Далее последовал ряд, в том числе инженерных работ, применяющих достижимость с контекстно-свободными ограничениями для анализа указателей, анализа алиасов и других прикладных задач~\sidecite{LabelFlowCFLReachability,specificationCFLReachability,Zheng}. + \item Графовые БД. + Впервые задача сформулирована Михалисом Яннакакисом~\sidecite{Yannakakis}. + Запросы с контекстно-свободными ограничениями нашли своё применение различных областях. + \begin{itemize} + \item Социальные сети~\sidecite{Hellings2015PathRF}. + \item RDF обработка~\sidecite{10.1007/978-3-319-46523-4_38}. + \item Биоинформатика~\sidecite{cfpqBio}. + \end{itemize} \end{itemize} %\begin{itemize} diff --git a/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex b/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex index 6ce1444..e445460 100644 --- a/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex +++ b/tex/FormalLanguageConstrainedReachabilityLectureNotes.tex @@ -47,7 +47,7 @@ \input{Context-Free_Languages} % \input{Multiple_Context-Free_Languages} % FIXME: Переписать главу % %\input{ConjunctiveAndBooleanLanguages} -% \input{FLPQ} +\input{FLPQ} % \input{RPQ} % %\input{CFPQ} % \input{CYK_for_CFPQ} From ac7a8fb01d6f4f3331a9fd8162c90adc612cae46 Mon Sep 17 00:00:00 2001 From: Nikolai Ponomarev Date: Thu, 20 Jun 2024 16:42:27 +0300 Subject: [PATCH 29/29] Fix order of loading packages mathtools must be loaded before unicode-math, otherwise some symbols become broken, e.g. underbrace. See latex3/mathtools#43 --- tex/FormalLanguageTheoryIntro.tex | 1 - tex/kao.sty | 2 ++ tex/styles/math.tex | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tex/FormalLanguageTheoryIntro.tex b/tex/FormalLanguageTheoryIntro.tex index b93d7f0..d220298 100644 --- a/tex/FormalLanguageTheoryIntro.tex +++ b/tex/FormalLanguageTheoryIntro.tex @@ -111,7 +111,6 @@ \section{Теоретико-множественные операции над При этом $S_1^0 = \{\varepsilon\}$% \sidenote{В данном случае нулевая степень даёт единицу, как мы и привыкли.}. \end{definition} -\marginnote{TODO: Я не понял, что со скобочкой стало} \begin{definition}[TODO: ???] Пусть дано множество $S$ с определённой на нём операцией $\odot: S \times S \to S$, $S_1 \subseteq S$, тогда diff --git a/tex/kao.sty b/tex/kao.sty index 5e5b33c..290be85 100644 --- a/tex/kao.sty +++ b/tex/kao.sty @@ -34,6 +34,8 @@ \let\Ifthispageodd\ifthispageodd% } +\RequirePackage{mathtools} % Superior to amsmath, but must be loaded before unicode-math + %---------------------------------------------------------------------------------------- % KAO-SPECIFIC OPTIONS %---------------------------------------------------------------------------------------- diff --git a/tex/styles/math.tex b/tex/styles/math.tex index 5a60756..8db8bad 100644 --- a/tex/styles/math.tex +++ b/tex/styles/math.tex @@ -1,4 +1,4 @@ -\usepackage{amsmath, amsfonts, amssymb, amsthm, mathtools} % Advanced math tools. +\usepackage{amsthm} \usepackage{nicematrix} % \setmathfont[range={\doubleplus}, Scale=MatchLowercase]{Asana Math}