You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Заметим, что функцию переходов можно представить разными способами: это может быть множество троек вида $(q_i, t, q_j)$, матрица, или же граф с метками на рёбрах
119
119
\[G = \langle Q, \{(q_i,t,q_j \mid q_j \in\delta(q_i,t))\}, \Sigma\rangle.\]
120
120
В дальнейшем мы чаще всего будем использовать представление автомата в виде графа.
121
-
Чтобы такое представление было полным, в графе отдельно обозначают стартовые и финальные состояния, как это показано на рисунке~\ref{fa:fa_example}.
121
+
Чтобы такое представление было полным, в графе отдельно обозначают стартовые и финальные состояния, как это показано на рисунке~\ref{fig:nfa_example}.
122
122
123
123
Так как нас интересуют конечные автоматы в контексте языков, то будем говорить, что на ленте автомата записано какое-то слово (или строка).
124
124
Иными словами, будем говорить, что автомат принимает на вход слово или строку.
Тогда его можно представить в виде графа как показано на рисунке~\ref{fa:fa_example}.
141
+
Тогда его можно представить в виде графа как показано на рисунке~\ref{fig:nfa_example}.
142
142
\begin{marginfigure}
143
143
\begin{center}
144
144
\begin{tikzpicture}
@@ -154,7 +154,7 @@ \section{Конечные автоматы}
154
154
\end{tikzpicture}
155
155
\end{center}
156
156
\caption{Пример конечного автомата в котором состояние $0$~--- стартовое, а состояние $1$~--- финальное}
157
-
\label{fa:fa_example}
157
+
\label{fig:nfa_example}
158
158
\end{marginfigure}
159
159
\end{example}
160
160
@@ -216,7 +216,7 @@ \section{Конечные автоматы}
216
216
Это поможет при написании реального интерпретатора: будем отслеживать уже посещённые (обработанные) конфигурации\sidenote{Техника, аналогичная той, что применяется в обходах графов (обход в ширину, обход в глубину) для того, чтобы избежать повторного посещения вершин и, как следствие, зацикливания обхода. Более того, она типична для алгоритмов с рабочим множеством.}.
217
217
218
218
\begin{example}
219
-
Рассмотрим пример работы конечного автомата, представленного на рисунке~\ref{fa:fa_example}, на входной цепочке \texttt{abb}.
219
+
Рассмотрим пример работы конечного автомата, представленного на рисунке~\ref{fig:nfa_example}, на входной цепочке \texttt{abb}.
220
220
В данном автомате стартовое состояние одно, потому множество стартовых конфигураций состоит из одной конфигурации:
221
221
\[
222
222
C_S = \{(0,\texttt{abb})\}.
@@ -262,7 +262,7 @@ \section{Конечные автоматы}
262
262
Во-первых, стартовое состояние ровно одно.
263
263
Во-вторых, функция переходов не допускает переходов по $\varepsilon$ и из любого состояния существует не более одного перехода по конкретному символу.
264
264
265
-
\begin{example}
265
+
\begin{example}\label{example:DFA}
266
266
Пусть задан детерминированный автомат $M=\langle Q, q_S, Q_F, \delta, \Sigma\rangle$, где
267
267
\begin{itemize}
268
268
\item$Q = \{0,1,2\}$;
@@ -409,22 +409,113 @@ \section{Производные для регулярных языков}
409
409
410
410
\section{Построение конечного автомата по регулярному выражению}
411
411
412
-
На производных%
412
+
Конечные автоматы и регулярные выражения --- два способа задать оди и тот же класс языков.
413
+
Для того, чтобы убедиться в их равной выразительной силе, для начала, научимся строить конечный автомат по регулярному выражению.
414
+
Использование производных позволит нам сразу построить полный детерминированный автомат%
413
415
\sidenote{Существуют и другие алгоритмы построения автомата по регулярному выражению. Например, алгоритм Томпсона~\cite{10.1145/363347.363387} или алгоритм Глушкова~\cite{Glushkov1961}.
414
416
Как правило, каждый алгоритм строит автомат со специфичными свойствами: детерминированный или нет, с $\varepsilon$-переходами или без них.}.
415
417
416
-
Каждое состояние соответствует языку, распозноваемому из этого состояния.
418
+
Состояниям автомата будут соответствовать регулярные выражения: если (в результирующем автомате) состояние выбрать стартовым, то получившийся автомат будет распознавать язык, задаваемый соответствующим регулярным выражением.
419
+
Чтобы автомат был минимальным нам будет необходимо проверять на эквивалентность языки, задаваемые регулярными выражениями и не дублировать состояния.
420
+
Хотя задача проверки эквивалентности регулярных языков разрешима, на практике, в рамках данного алгоритма, чаще пользуются более быстро проверяемой структурной эквивалентностью~\sidenote{На деле, при проверке структурной эквивалентности дополнительно пользуются знаниями об ассоциативности некоторых операций и другимим свойствами выражений.} регулярных выражений~\sidecite{OWENS_REPPY_TURON_2009}.
421
+
417
422
418
-
Стартовое --- исходное регулярное выражение. Далее в цикле.
423
+
Таким образом, получится алгоритм с рабочим множеством, который состоит в следующем.
424
+
В качестве стартового состояния возьмём состояние, соответствующее исходному регулярному выражению.
425
+
В рабочее множество добавим стартовое состояние.
426
+
Далее, пока рабочее множество не пусто, в цикле повторяем следующие шаги.
427
+
\btgin{enumerate}
428
+
\item Берём из множества очередное состояние $q$, соответствующее регулярному выражению $R_q$.
429
+
\item Для всех символов из алфавита вычисляем производные $R_q$:.
430
+
\item Для всех построенных состояний проверяем, существует ли уже
431
+
\end{enumerate}
419
432
Берём очередное необработанное состояние, по каждому символу из алфавита берём производную соответствующего ему регулярного выражения.
420
433
Добавляем получившееся состояние (если ещё не было такого).
421
434
Если состояние isNullable, то помечаем его финальным.
422
435
Добавляем ребро.
423
436
424
-
В результате получим полный детерминированный конечный автомат\sidenote{Формально можно получить минимальный, но на практике это сложно. Но часто всё же достаточно близко к минимальному получается.}.
437
+
В результате получим полный детерминированный конечный автомат\sidenote{Формально, если честно проверять равенство языков, можно получить минимальный, но на практике это сложно. Но часто всё же достаточно близко к минимальному получается.}.
425
438
426
-
Примеры.
439
+
\begin{example}
440
+
Построим автомат по регулярному выражению $a(a \mid (b \ b))^*$.
441
+
Состояние, помеченное данным выражением назначим стартовым и вычислим производные по символам.
442
+
Так как $\emph{IsNull}(a(a \mid (b \ b))^*) = \emph{false}$, финальным данное состояние не является.
443
+
Вычислим производные исходного выражения по всем символам из алфавита.
444
+
Проверим, что получившиеся выражения задают различные языки и добавим соответствующие переходы.
445
+
Одно из состояний соответствует пустому языку.
446
+
Данное состояние будет <<дьявольским>> или <<стоком>>.
\caption{Пример детерминированного конечного автомата в }
512
+
\label{fig:regexp_to_dfa_example_step_3}
513
+
\end{marginfigure}
514
+
\end{example}
427
515
516
+
В результате построения мы получили автомат, очень похожий на автомат из примера~\ref{example:DFA}.
517
+
Единственная разница заключается в том, что автомат из примера не является полным.
518
+
Само же сходство не случайно: автоматы действительно задают один и тот же регулярный язык.
428
519
429
520
\section{Построение регулярного выражения по конечному автомату}
430
521
@@ -518,7 +609,6 @@ \section{Построение регулярного выражения по к
518
609
519
610
\end{tikzpicture}
520
611
\end{center}
521
-
522
612
\caption{Автомат перед устранением состояния $v$}
523
613
\label{fa:fa3}
524
614
@@ -559,8 +649,8 @@ \section{Построение регулярного выражения по к
559
649
\end{figure}
560
650
561
651
После завершения основного цикла (когда в автомате осталось ровно два состояния), необходимо ещё раз объединить параллельные рёбра.
562
-
Общий вид получившегося автомата представлен на рисунке~\ref{fa:fa5}.
563
-
По такому автомату строим выражение вида \[(R_1^* \cdot (R_2 \cdot R_3^* \cdot R_4 )^* \cdot R_2 \cdot R_3^*,\] которое и будет ответом.
652
+
Общий вид получившегося автомата представлен на рисунке~\ref{fig:fa_to_regexp_final}.
653
+
По такому автомату строим выражение вида \[(R_1^* \cdot (R_2 \cdot R_3^* \cdot R_4 \cdot R_1^*)^* \cdot R_2 \cdot R_3^*,\] которое и будет ответом.
564
654
\begin{marginfigure}
565
655
566
656
\begin{center}
@@ -579,12 +669,42 @@ \section{Построение регулярного выражения по к
579
669
\end{center}
580
670
581
671
\caption{Общий вид автомата после завершения основного цикла}
582
-
\label{fa:fa5}
672
+
\label{fig:fa_to_regexp_final}
583
673
584
674
\end{marginfigure}
585
675
586
676
\begin{example}
587
-
Примеры.
677
+
Построим регулярное выражение по автомату, представленному на рисунке~\ref{fig:nfa_example}.
678
+
В автомате уже одно финальное и одно стартовое состояние.
679
+
При этом, существует всего одно состояние, которое не является ни финальным, ни стартовым.
680
+
Это состояние \circled{2}.
681
+
Его и устраним.
682
+
683
+
После устранения состояния \circled{2} получим автомат, представленный на рисунке~\ref{fig:nfa_to_regexp}.
684
+
Теперь наш автомат принял вид, соответствующий представленному на рисунке~\ref{fig:fa_to_regexp_final}, и можно выписать результирующее регулярное выражение, которое будет иметь следующий вид%
685
+
\sidenote{Конесно, получившесея выражение не <<минимально>>: дослаточно легко можно придумать более простое и компактное регулярное выражение, задающее тот же самый язык.
686
+
Но алгоритм нам и не обещал ни каких дополнительных свойств получившегося выражения.}:
0 commit comments