http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&user=Zernov&feedformat=atomВикиконспекты - Вклад участника [ru]2024-03-28T08:58:04ZВклад участникаMediaWiki 1.30.0http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58799Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-05T13:48:14Z<p>Zernov: /* Алгоритм */</p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]]. Главным отличием от базовой версии алгоритма является функция <tex>\mathtt{rulesLoop}</tex>, внутри которой мы, как и в базовой версии, просматриваем второе и третье правило, однако, в отличие от базовой версии, где при каждом изменении <tex>D_j</tex> мы просматривали весь список <tex>D_j</tex> и применяли к нему второе и третье правило, в модифицированной версии мы применяем правила внутри <tex>\mathtt{rulesLoop}</tex>, просматривая только те ситуации, которые были добавлены на предыдущей итерации цикла <tex>\mathtt{while}</tex>.<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
'''function''' <tex>\mathtt{earleyMod}(G, w)</tex>:<br />
<font color=green>// Инициализация </font><br />
<tex> D_{0} = \lbrace [S' \rightarrow \cdot S, 0] \rbrace </tex><br />
rulesLoop(0)<br />
'''for''' j = 1 .. n<br />
'''for''' <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in D_{j-1}</tex><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> <font color=green>// Первое правило </font><br />
rulesLoop(j) <br />
<br />
'''function''' <tex>\mathtt{rulesLoop(j)}</tex>:<br />
<tex>D_j'' = D_j</tex><br />
'''while''' <tex>D_j'' \ne \varnothing</tex><br />
<tex>D_j' = D_j''</tex><br />
<tex>D_j'' = \varnothing</tex><br />
'''for''' <tex>[B \rightarrow \eta \cdot , i] \in D_j'</tex> <font color=green>// Цикл (*) </font><br />
'''for''' <tex>[A \rightarrow \alpha \cdot B \beta, k] \in D_{i}</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha B \cdot \beta, k] </tex> <font color=green>// Второе правило </font><br />
<br />
'''for''' <tex>[B \rightarrow \alpha \cdot A \eta, k] \in D_j'</tex> <font color=green>// Цикл (**) </font><br />
'''for''' <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \cdot \beta, j]</tex> <font color=green>// Третье правило </font><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>D_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>D_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <tex>\mathrm{while}</tex>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \leqslant j \leqslant n</tex> в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>D_j</tex> находятся ситуации, у которых <tex>0 \leqslant i \leqslant j</tex>, всего в <tex>D_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>D_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>D_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>D_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>D_{k_1}</tex> и в <tex>D_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию. <br />
<br />
Суммируя выше сказанное, отметим, что противоречие получается из того факта, что в некоторый момент времени (то есть для подстроки <tex>a_1 \dots a_i</tex>) мы получаем два различных дерева вывода. Поэтому, в дальнейшем, при выводе суффикса <tex>a_{i+1} \dots a_n</tex>, каким образом мы его не получим, деревьев вывода будет как минимум два, поскольку они будут получаться заменой какого-то листа (терминального символа) на какое-то правило (поддерево из нетерминалов и терминалов),таким образом, получаем противоречие с однозначностью (по определению [[Существенно_неоднозначные_языки | неоднозачной грамматики]])<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>D_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>D_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>D_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>D_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex> следующим образом: каждый раз, когда мы добавляем ситацаию вида <tex>[A \rightarrow \alpha \cdot B \beta, i]</tex> в <tex>D_j</tex>, мы просмотрим в заранее заготовленном массиве для <tex>D_j</tex>, есть ли в <tex>D_j</tex> ситуации вида <tex>[B \rightarrow \eta \cdot, j]</tex>. Если да, то добавим <tex>[A \rightarrow \alpha B \cdot \beta, i]</tex> в <tex>D_j</tex>.). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>D_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ. Издательство "Мир", Москва, 1978г., стр. 364-366<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: Алгоритмы разбора]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58798Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-05T13:41:27Z<p>Zernov: /* Источники информации */</p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]].<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
'''function''' <tex>\mathtt{earleyMod}(G, w)</tex>:<br />
<font color=green>// Инициализация </font><br />
<tex> D_{0} = \lbrace [S' \rightarrow \cdot S, 0] \rbrace </tex><br />
rulesLoop(0)<br />
'''for''' j = 1 .. n<br />
'''for''' <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in D_{j-1}</tex><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> <font color=green>// Первое правило </font><br />
rulesLoop(j) <br />
<br />
'''function''' <tex>\mathtt{rulesLoop(j)}</tex>:<br />
<tex>D_j'' = D_j</tex><br />
'''while''' <tex>D_j'' \ne \varnothing</tex><br />
<tex>D_j' = D_j''</tex><br />
<tex>D_j'' = \varnothing</tex><br />
'''for''' <tex>[B \rightarrow \eta \cdot , i] \in D_j'</tex> <font color=green>// Цикл (*) </font><br />
'''for''' <tex>[A \rightarrow \alpha \cdot B \beta, k] \in D_{i}</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha B \cdot \beta, k] </tex> <font color=green>// Второе правило </font><br />
<br />
'''for''' <tex>[B \rightarrow \alpha \cdot A \eta, k] \in D_j'</tex> <font color=green>// Цикл (**) </font><br />
'''for''' <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \cdot \beta, j]</tex> <font color=green>// Третье правило </font><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>D_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>D_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <tex>\mathrm{while}</tex>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \leqslant j \leqslant n</tex> в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>D_j</tex> находятся ситуации, у которых <tex>0 \leqslant i \leqslant j</tex>, всего в <tex>D_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>D_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>D_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>D_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>D_{k_1}</tex> и в <tex>D_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию. <br />
<br />
Суммируя выше сказанное, отметим, что противоречие получается из того факта, что в некоторый момент времени (то есть для подстроки <tex>a_1 \dots a_i</tex>) мы получаем два различных дерева вывода. Поэтому, в дальнейшем, при выводе суффикса <tex>a_{i+1} \dots a_n</tex>, каким образом мы его не получим, деревьев вывода будет как минимум два, поскольку они будут получаться заменой какого-то листа (терминального символа) на какое-то правило (поддерево из нетерминалов и терминалов),таким образом, получаем противоречие с однозначностью (по определению [[Существенно_неоднозначные_языки | неоднозачной грамматики]])<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>D_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>D_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>D_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>D_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex> следующим образом: каждый раз, когда мы добавляем ситацаию вида <tex>[A \rightarrow \alpha \cdot B \beta, i]</tex> в <tex>D_j</tex>, мы просмотрим в заранее заготовленном массиве для <tex>D_j</tex>, есть ли в <tex>D_j</tex> ситуации вида <tex>[B \rightarrow \eta \cdot, j]</tex>. Если да, то добавим <tex>[A \rightarrow \alpha B \cdot \beta, i]</tex> в <tex>D_j</tex>.). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>D_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ. Издательство "Мир", Москва, 1978г., стр. 364-366<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: Алгоритмы разбора]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58797Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-05T13:39:18Z<p>Zernov: </p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]].<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
'''function''' <tex>\mathtt{earleyMod}(G, w)</tex>:<br />
<font color=green>// Инициализация </font><br />
<tex> D_{0} = \lbrace [S' \rightarrow \cdot S, 0] \rbrace </tex><br />
rulesLoop(0)<br />
'''for''' j = 1 .. n<br />
'''for''' <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in D_{j-1}</tex><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> <font color=green>// Первое правило </font><br />
rulesLoop(j) <br />
<br />
'''function''' <tex>\mathtt{rulesLoop(j)}</tex>:<br />
<tex>D_j'' = D_j</tex><br />
'''while''' <tex>D_j'' \ne \varnothing</tex><br />
<tex>D_j' = D_j''</tex><br />
<tex>D_j'' = \varnothing</tex><br />
'''for''' <tex>[B \rightarrow \eta \cdot , i] \in D_j'</tex> <font color=green>// Цикл (*) </font><br />
'''for''' <tex>[A \rightarrow \alpha \cdot B \beta, k] \in D_{i}</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha B \cdot \beta, k] </tex> <font color=green>// Второе правило </font><br />
<br />
'''for''' <tex>[B \rightarrow \alpha \cdot A \eta, k] \in D_j'</tex> <font color=green>// Цикл (**) </font><br />
'''for''' <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \cdot \beta, j]</tex> <font color=green>// Третье правило </font><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>D_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>D_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <tex>\mathrm{while}</tex>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \leqslant j \leqslant n</tex> в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>D_j</tex> находятся ситуации, у которых <tex>0 \leqslant i \leqslant j</tex>, всего в <tex>D_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>D_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>D_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>D_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>D_{k_1}</tex> и в <tex>D_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию. <br />
<br />
Суммируя выше сказанное, отметим, что противоречие получается из того факта, что в некоторый момент времени (то есть для подстроки <tex>a_1 \dots a_i</tex>) мы получаем два различных дерева вывода. Поэтому, в дальнейшем, при выводе суффикса <tex>a_{i+1} \dots a_n</tex>, каким образом мы его не получим, деревьев вывода будет как минимум два, поскольку они будут получаться заменой какого-то листа (терминального символа) на какое-то правило (поддерево из нетерминалов и терминалов),таким образом, получаем противоречие с однозначностью (по определению [[Существенно_неоднозначные_языки | неоднозачной грамматики]])<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>D_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>D_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>D_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>D_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex> следующим образом: каждый раз, когда мы добавляем ситацаию вида <tex>[A \rightarrow \alpha \cdot B \beta, i]</tex> в <tex>D_j</tex>, мы просмотрим в заранее заготовленном массиве для <tex>D_j</tex>, есть ли в <tex>D_j</tex> ситуации вида <tex>[B \rightarrow \eta \cdot, j]</tex>. Если да, то добавим <tex>[A \rightarrow \alpha B \cdot \beta, i]</tex> в <tex>D_j</tex>.). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>D_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ.<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58796Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-05T13:38:45Z<p>Zernov: /* Доказательство эквивалентности */</p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]].<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
'''function''' <tex>\mathtt{earleyMod}(G, w)</tex>:<br />
<font color=green>// Инициализация </font><br />
<tex> D_{0} = \lbrace [S' \rightarrow \cdot S, 0] \rbrace </tex><br />
rulesLoop(0)<br />
'''for''' j = 1 .. n<br />
'''for''' <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in D_{j-1}</tex><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> <font color=green>// Первое правило </font><br />
rulesLoop(j) <br />
<br />
'''function''' <tex>\mathtt{rulesLoop(j)}</tex>:<br />
<tex>D_j'' = D_j</tex><br />
'''while''' <tex>D_j'' \ne \varnothing</tex><br />
<tex>D_j' = D_j''</tex><br />
<tex>D_j'' = \varnothing</tex><br />
'''for''' <tex>[B \rightarrow \eta \cdot , i] \in D_j'</tex> <font color=green>// Цикл (*) </font><br />
'''for''' <tex>[A \rightarrow \alpha \cdot B \beta, k] \in D_{i}</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha B \cdot \beta, k] </tex> <font color=green>// Второе правило </font><br />
<br />
'''for''' <tex>[B \rightarrow \alpha \cdot A \eta, k] \in D_j'</tex> <font color=green>// Цикл (**) </font><br />
'''for''' <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \cdot \beta, j]</tex> <font color=green>// Третье правило </font><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>D_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>D_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <tex>\mathrm{while}</tex>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \le j \le n</tex> в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>D_j</tex> находятся ситуации, у которых <tex>0 \le i \le j</tex>, всего в <tex>D_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>D_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>D_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>D_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>D_{k_1}</tex> и в <tex>D_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию. <br />
<br />
Суммируя выше сказанное, отметим, что противоречие получается из того факта, что в некоторый момент времени (то есть для подстроки <tex>a_1 \dots a_i</tex>) мы получаем два различных дерева вывода. Поэтому, в дальнейшем, при выводе суффикса <tex>a_{i+1} \dots a_n</tex>, каким образом мы его не получим, деревьев вывода будет как минимум два, поскольку они будут получаться заменой какого-то листа (терминального символа) на какое-то правило (поддерево из нетерминалов и терминалов),таким образом, получаем противоречие с однозначностью (по определению [[Существенно_неоднозначные_языки | неоднозачной грамматики]])<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>D_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>D_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>D_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>D_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex> следующим образом: каждый раз, когда мы добавляем ситацаию вида <tex>[A \rightarrow \alpha \cdot B \beta, i]</tex> в <tex>D_j</tex>, мы просмотрим в заранее заготовленном массиве для <tex>D_j</tex>, есть ли в <tex>D_j</tex> ситуации вида <tex>[B \rightarrow \eta \cdot, j]</tex>. Если да, то добавим <tex>[A \rightarrow \alpha B \cdot \beta, i]</tex> в <tex>D_j</tex>.). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>D_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ.<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58795Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-05T13:37:47Z<p>Zernov: /* Алгоритм */</p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]].<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
'''function''' <tex>\mathtt{earleyMod}(G, w)</tex>:<br />
<font color=green>// Инициализация </font><br />
<tex> D_{0} = \lbrace [S' \rightarrow \cdot S, 0] \rbrace </tex><br />
rulesLoop(0)<br />
'''for''' j = 1 .. n<br />
'''for''' <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in D_{j-1}</tex><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> <font color=green>// Первое правило </font><br />
rulesLoop(j) <br />
<br />
'''function''' <tex>\mathtt{rulesLoop(j)}</tex>:<br />
<tex>D_j'' = D_j</tex><br />
'''while''' <tex>D_j'' \ne \varnothing</tex><br />
<tex>D_j' = D_j''</tex><br />
<tex>D_j'' = \varnothing</tex><br />
'''for''' <tex>[B \rightarrow \eta \cdot , i] \in D_j'</tex> <font color=green>// Цикл (*) </font><br />
'''for''' <tex>[A \rightarrow \alpha \cdot B \beta, k] \in D_{i}</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha B \cdot \beta, k] </tex> <font color=green>// Второе правило </font><br />
<br />
'''for''' <tex>[B \rightarrow \alpha \cdot A \eta, k] \in D_j'</tex> <font color=green>// Цикл (**) </font><br />
'''for''' <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \cdot \beta, j]</tex> <font color=green>// Третье правило </font><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>D_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>D_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <code>while</code>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \le j \le n</tex> в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>D_j</tex> находятся ситуации, у которых <tex>0 \le i \le j</tex>, всего в <tex>D_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>D_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>D_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>D_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>D_{k_1}</tex> и в <tex>D_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию. <br />
<br />
Суммируя выше сказанное, отметим, что противоречие получается из того факта, что в некоторый момент времени (то есть для подстроки <tex>a_1 \dots a_i</tex>) мы получаем два различных дерева вывода. Поэтому, в дальнейшем, при выводе суффикса <tex>a_{i+1} \dots a_n</tex>, каким образом мы его не получим, деревьев вывода будет как минимум два, поскольку они будут получаться заменой какого-то листа (терминального символа) на какое-то правило (поддерево из нетерминалов и терминалов),таким образом, получаем противоречие с однозначностью (по определению [[Существенно_неоднозначные_языки | неоднозачной грамматики]])<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>D_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>D_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>D_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>D_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex> следующим образом: каждый раз, когда мы добавляем ситацаию вида <tex>[A \rightarrow \alpha \cdot B \beta, i]</tex> в <tex>D_j</tex>, мы просмотрим в заранее заготовленном массиве для <tex>D_j</tex>, есть ли в <tex>D_j</tex> ситуации вида <tex>[B \rightarrow \eta \cdot, j]</tex>. Если да, то добавим <tex>[A \rightarrow \alpha B \cdot \beta, i]</tex> в <tex>D_j</tex>.). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>D_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ.<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58739Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-04T21:06:47Z<p>Zernov: /* Время работы для однозначной грамматики */</p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]].<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
'''function''' <tex>\mathtt{earley_mod}(G, w)</tex>:<br />
<font color=green>// Инициализация </font><br />
<tex> D_{0} = \lbrace [S' \rightarrow \cdot S, 0] \rbrace </tex><br />
useful_loop(0)<br />
'''for''' j = 1 .. n<br />
'''for''' <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in D_{j-1}</tex><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> <font color=green>// Первое правило </font><br />
useful_loop(j) <br />
<br />
'''function''' useful_loop(j):<br />
<tex>D_j'' = D_j</tex><br />
'''while''' <tex>D_j'' \ne \varnothing</tex><br />
<tex>D_j' = D_j''</tex><br />
<tex>D_j'' = \varnothing</tex><br />
'''for''' <tex>[B \rightarrow \eta \cdot , i] \in D_j'</tex> <font color=green>// Цикл (*) </font><br />
'''for''' <tex>[A \rightarrow \alpha \cdot B \beta, k] \in D_{i}</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha B \cdot \beta, k] </tex> <font color=green>// Второе правило </font><br />
<br />
'''for''' <tex>[B \rightarrow \alpha \cdot A \eta, k] \in D_j'</tex> <font color=green>// Цикл (**) </font><br />
'''for''' <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \cdot \beta, j]</tex> <font color=green>// Третье правило </font><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>D_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>D_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <code>while</code>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \le j \le n</tex> в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>D_j</tex> находятся ситуации, у которых <tex>0 \le i \le j</tex>, всего в <tex>D_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>D_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>D_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>D_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>D_{k_1}</tex> и в <tex>D_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию. <br />
<br />
Суммируя выше сказанное, отметим, что противоречие получается из того факта, что в некоторый момент времени (то есть для подстроки <tex>a_1 \dots a_i</tex>) мы получаем два различных дерева вывода. Поэтому, в дальнейшем, при выводе суффикса <tex>a_{i+1} \dots a_n</tex>, каким образом мы его не получим, деревьев вывода будет как минимум два, поскольку они будут получаться заменой какого-то листа (терминального символа) на какое-то правило (поддерево из нетерминалов и терминалов),таким образом, получаем противоречие с однозначностью (по определению [[Существенно_неоднозначные_языки | неоднозачной грамматики]])<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>D_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>D_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>D_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>D_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex> следующим образом: каждый раз, когда мы добавляем ситацаию вида <tex>[A \rightarrow \alpha \cdot B \beta, i]</tex> в <tex>D_j</tex>, мы просмотрим в заранее заготовленном массиве для <tex>D_j</tex>, есть ли в <tex>D_j</tex> ситуации вида <tex>[B \rightarrow \eta \cdot, j]</tex>. Если да, то добавим <tex>[A \rightarrow \alpha B \cdot \beta, i]</tex> в <tex>D_j</tex>.). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>D_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ.<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58728Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-04T20:52:18Z<p>Zernov: /* Время работы для однозначной грамматики */</p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]].<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
'''function''' <tex>\mathtt{earley_mod}(G, w)</tex>:<br />
<font color=green>// Инициализация </font><br />
<tex> D_{0} = \lbrace [S' \rightarrow \cdot S, 0] \rbrace </tex><br />
useful_loop(0)<br />
'''for''' j = 1 .. n<br />
'''for''' <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in D_{j-1}</tex><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> <font color=green>// Первое правило </font><br />
useful_loop(j) <br />
<br />
'''function''' useful_loop(j):<br />
<tex>D_j'' = D_j</tex><br />
'''while''' <tex>D_j'' \ne \varnothing</tex><br />
<tex>D_j' = D_j''</tex><br />
<tex>D_j'' = \varnothing</tex><br />
'''for''' <tex>[B \rightarrow \eta \cdot , i] \in D_j'</tex> <font color=green>// Цикл (*) </font><br />
'''for''' <tex>[A \rightarrow \alpha \cdot B \beta, k] \in D_{i}</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha B \cdot \beta, k] </tex> <font color=green>// Второе правило </font><br />
<br />
'''for''' <tex>[B \rightarrow \alpha \cdot A \eta, k] \in D_j'</tex> <font color=green>// Цикл (**) </font><br />
'''for''' <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \cdot \beta, j]</tex> <font color=green>// Третье правило </font><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>D_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>D_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <code>while</code>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \le j \le n</tex> в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>D_j</tex> находятся ситуации, у которых <tex>0 \le i \le j</tex>, всего в <tex>D_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>D_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>D_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>D_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>D_{k_1}</tex> и в <tex>D_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию. <br />
<br />
Суммируя выше сказанное, отметим, что противоречие получается из того факта, что в некоторый момент времени (то есть для подстроки <tex>a_1 \dots a_i</tex>) мы получаем два различных дерева вывода. Поэтому, в дальнейшем, при выводе суффикса <tex>a_{i+1} \dots a_n</tex>, каким образом мы его не получим, деревьев вывода будет как минимум два, поскольку они будут получаться заменой какого-то листа (терминального символа) на какое-то правило (поддерево из нетерминалов и терминалов),таким образом, получаем противоречие с однозначностью (по определению [[Существенно_неоднозначные_языки | неоднозачной грамматики]])<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>D_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>D_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>D_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>D_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex>). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>D_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ.<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58726Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-04T20:33:40Z<p>Zernov: </p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]].<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
'''function''' <tex>\mathtt{earley_mod}(G, w)</tex>:<br />
<font color=green>// Инициализация </font><br />
<tex> D_{0} = \lbrace [S' \rightarrow \cdot S, 0] \rbrace </tex><br />
useful_loop(0)<br />
'''for''' j = 1 .. n<br />
'''for''' <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in D_{j-1}</tex><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> <font color=green>// Первое правило </font><br />
useful_loop(j) <br />
<br />
'''function''' useful_loop(j):<br />
<tex>D_j'' = D_j</tex><br />
'''while''' <tex>D_j'' \ne \varnothing</tex><br />
<tex>D_j' = D_j''</tex><br />
<tex>D_j'' = \varnothing</tex><br />
'''for''' <tex>[B \rightarrow \eta \cdot , i] \in D_j'</tex> <font color=green>// Цикл (*) </font><br />
'''for''' <tex>[A \rightarrow \alpha \cdot B \beta, k] \in D_{i}</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha B \cdot \beta, k] </tex> <font color=green>// Второе правило </font><br />
<br />
'''for''' <tex>[B \rightarrow \alpha \cdot A \eta, k] \in D_j'</tex> <font color=green>// Цикл (**) </font><br />
'''for''' <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \cdot \beta, j]</tex> <font color=green>// Третье правило </font><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>D_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>D_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <code>while</code>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \le j \le n</tex> в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>D_j</tex> находятся ситуации, у которых <tex>0 \le i \le j</tex>, всего в <tex>D_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>D_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>D_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>D_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>D_{k_1}</tex> и в <tex>D_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию.<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>D_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>D_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>D_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>D_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex>). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>D_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>D_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ.<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58725Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-04T20:32:52Z<p>Zernov: /* Алгоритм */</p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]].<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
'''function''' <tex>\mathtt{earley_mod}(G, w)</tex>:<br />
<font color=green>// Инициализация </font><br />
<tex> D_{0} = \lbrace [S' \rightarrow \cdot S, 0] \rbrace </tex><br />
useful_loop(0)<br />
'''for''' j = 1 .. n<br />
'''for''' <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in D_{j-1}</tex><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> <font color=green>// Первое правило </font><br />
useful_loop(j) <br />
<br />
'''function''' useful_loop(j):<br />
<tex>D_j'' = D_j</tex><br />
'''while''' <tex>D_j'' \ne \varnothing</tex><br />
<tex>D_j' = D_j''</tex><br />
<tex>D_j'' = \varnothing</tex><br />
'''for''' <tex>[B \rightarrow \eta \cdot , i] \in D_j'</tex> <font color=green>// Цикл (*) </font><br />
'''for''' <tex>[A \rightarrow \alpha \cdot B \beta, k] \in D_{i}</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \alpha B \cdot \beta, k] </tex> <font color=green>// Второе правило </font><br />
<br />
'''for''' <tex>[B \rightarrow \alpha \cdot A \eta, k] \in D_j'</tex> <font color=green>// Цикл (**) </font><br />
'''for''' <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>D_j''</tex> <tex> \cup</tex> = <tex>[A \rightarrow \cdot \beta, j]</tex> <font color=green>// Третье правило </font><br />
<tex>D_j</tex> <tex> \cup</tex> = <tex>D_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>I_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <code>while</code>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \le j \le n</tex> в списке <tex>I_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>I_j</tex> находятся ситуации, у которых <tex>0 \le i \le j</tex>, всего в <tex>I_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>I_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>I_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>I_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>I_{k_1}</tex> и в <tex>I_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию.<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>I_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>I_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>I_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>I_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex>). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>I_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>I_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ.<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58707Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-04T19:15:00Z<p>Zernov: /* Время работы для однозначной грамматики */</p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]].<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
<tex>I_0</tex> = <tex>\{[S' \rightarrow \cdot S, 0]\}</tex> # Правило (0) — инициализация<br />
useful_loop(0)<br />
<br />
for j = 1..n<br />
for <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in I_{j-1}</tex><br />
<tex>I_j</tex> &cup;= <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> # Правило (1)<br />
useful_loop(j)<br />
<br />
function useful_loop(j):<br />
<tex>I_j'' = I_j</tex><br />
while <tex>I_j'' \ne \varnothing</tex><br />
<tex>I_j' = I_j''</tex><br />
<tex>I_j'' = \varnothing</tex><br />
for <tex>[B \rightarrow \eta \cdot , i] \in I_j'</tex> # (*)<br />
for <tex>[A \rightarrow \alpha \cdot B \beta, k] \in I_{i}</tex><br />
<tex>I_j''</tex> &cup;= <tex>[A \rightarrow \alpha B \cdot \beta, k]</tex> # Правило (2)<br />
<br />
for <tex>[B \rightarrow \alpha \cdot A \eta, k] \in I_j'</tex> # (**)<br />
for <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>I_j''</tex> &cup;= <tex>[A \rightarrow \cdot \beta, j]</tex> # Правило (3)<br />
<tex>I_j</tex> &cup;= <tex>I_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>I_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <code>while</code>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \le j \le n</tex> в списке <tex>I_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>I_j</tex> находятся ситуации, у которых <tex>0 \le i \le j</tex>, всего в <tex>I_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>\Gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>I_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>I_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>I_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>I_{k_1}</tex> и в <tex>I_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию.<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>I_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>I_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>I_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>I_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex>). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>I_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>I_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ.<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58706Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-04T19:14:36Z<p>Zernov: </p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]].<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
<tex>I_0</tex> = <tex>\{[S' \rightarrow \cdot S, 0]\}</tex> # Правило (0) — инициализация<br />
useful_loop(0)<br />
<br />
for j = 1..n<br />
for <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in I_{j-1}</tex><br />
<tex>I_j</tex> &cup;= <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> # Правило (1)<br />
useful_loop(j)<br />
<br />
function useful_loop(j):<br />
<tex>I_j'' = I_j</tex><br />
while <tex>I_j'' \ne \varnothing</tex><br />
<tex>I_j' = I_j''</tex><br />
<tex>I_j'' = \varnothing</tex><br />
for <tex>[B \rightarrow \eta \cdot , i] \in I_j'</tex> # (*)<br />
for <tex>[A \rightarrow \alpha \cdot B \beta, k] \in I_{i}</tex><br />
<tex>I_j''</tex> &cup;= <tex>[A \rightarrow \alpha B \cdot \beta, k]</tex> # Правило (2)<br />
<br />
for <tex>[B \rightarrow \alpha \cdot A \eta, k] \in I_j'</tex> # (**)<br />
for <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>I_j''</tex> &cup;= <tex>[A \rightarrow \cdot \beta, j]</tex> # Правило (3)<br />
<tex>I_j</tex> &cup;= <tex>I_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>I_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <code>while</code>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \le j \le n</tex> в списке <tex>I_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>I_j</tex> находятся ситуации, у которых <tex>0 \le i \le j</tex>, всего в <tex>I_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>\gamma = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>I_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>I_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>I_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>I_{k_1}</tex> и в <tex>I_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию.<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>I_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>I_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>I_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>I_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex>). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>I_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>I_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ.<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%AD%D1%80%D0%BB%D0%B8,_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B8_O(n%5E2)_%D0%B4%D0%BB%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%BD%D0%BE%D0%B9_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8&diff=58705Алгоритм Эрли, доказательство оценки O(n^2) для однозначной грамматики2017-01-04T19:13:21Z<p>Zernov: </p>
<hr />
<div>==Алгоритм==<br />
Для начала модифицируем [[Алгоритм Эрли|алгоритм Эрли]].<br />
<br />
Будем рассматривать грамматику [[Удаление eps-правил из грамматики|без &epsilon;-правил]] и [[Удаление бесполезных символов из грамматики|бесполезных символов]].<br />
<br />
<tex>I_0</tex> = <tex>\{[S' \rightarrow \cdot S, 0]\}</tex> # Правило (0) — инициализация<br />
useful_loop(0)<br />
<br />
for j = 1..n<br />
for <tex>[A \rightarrow \alpha \cdot a_{j} \beta, i] \in I_{j-1}</tex><br />
<tex>I_j</tex> &cup;= <tex>[A \rightarrow \alpha a_{j} \cdot \beta, i]</tex> # Правило (1)<br />
useful_loop(j)<br />
<br />
function useful_loop(j):<br />
<tex>I_j'' = I_j</tex><br />
while <tex>I_j'' \ne \varnothing</tex><br />
<tex>I_j' = I_j''</tex><br />
<tex>I_j'' = \varnothing</tex><br />
for <tex>[B \rightarrow \eta \cdot , i] \in I_j'</tex> # (*)<br />
for <tex>[A \rightarrow \alpha \cdot B \beta, k] \in I_{i}</tex><br />
<tex>I_j''</tex> &cup;= <tex>[A \rightarrow \alpha B \cdot \beta, k]</tex> # Правило (2)<br />
<br />
for <tex>[B \rightarrow \alpha \cdot A \eta, k] \in I_j'</tex> # (**)<br />
for <tex>\beta : (A \rightarrow \beta) \in P</tex><br />
<tex>I_j''</tex> &cup;= <tex>[A \rightarrow \cdot \beta, j]</tex> # Правило (3)<br />
<tex>I_j</tex> &cup;= <tex>I_j''</tex><br />
<br />
== Доказательство эквивалентности ==<br />
<br />
В циклах, помеченных <tex>(*)</tex> и <tex>(**)</tex>, просматривается не весь список <tex>I_j</tex>, а только те ситуации, которые были добавлены на предыдущей итерации цикла <code>while</code>. Данная модификация является корректной.<br />
# Рассмотрим цикл <tex>(*)</tex>. Если в текущей ситуации <tex>[B \rightarrow \eta \cdot, i]</tex> этого цикла <tex>i \ne j</tex>, то во внутреннем цикле просматривается список с меньшим индексом, в который новые ситуации больше не добавляются. Поэтому после первого просмотра этого списка будут добавлены все ситуации, удовлетворяющие условию, и больше ситуацию <tex>[B \rightarrow \eta \cdot, i]</tex> в цикле <tex>(*)</tex> рассматривать не нужно. Если же <tex>i = j</tex>, то <tex>\eta \Rightarrow^* \varepsilon</tex>, что возможно, только если <tex>B = S', \eta = \varepsilon</tex>. Тогда во внутреннем цикле не будет добавлено ни одной ситуации, так как <tex>S'</tex> не встречается в правых частях правил.<br />
# Теперь рассмотрим цикл <tex>(**)</tex>. Так как для каждой ситуации <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex> в список добавляется новая ситуация, соответствующая правилу из грамматики, а грамматика фиксирована, то после первого просмотра будут добавлены все возможные ситуации для <tex>[B \rightarrow \alpha \cdot A \eta, k]</tex>.<br />
Таким образом, во все списки будут добавлены ситуации, которые были бы добавлены в ходе обычного алгоритма. Очевидно, что лишних ситуаций добавлено не будет, так как в циклах <tex>(*)</tex> и <tex>(**)</tex> просматривается подмножество полного списка. Значит этот алгоритм эквивалентен оригинальному.<br />
<br />
==Время работы для однозначной грамматики==<br />
{{Лемма<br />
|about=1<br />
|statement=<br />
<tex>\forall\,j: 1 \le j \le n</tex> в списке <tex>I_j</tex> находится <tex>O(j)</tex> ситуаций.<br />
|proof=<br />
Так как грамматика фиксирована, то <tex>\forall i</tex> количество ситуаций вида <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> не больше некоторой константы. Таким образом, поскольку в <tex>I_j</tex> находятся ситуации, у которых <tex>0 \le i \le j</tex>, всего в <tex>I_j</tex> будет <tex>O(j)</tex> ситуаций.<br />
}}<br />
<br />
<br />
{{Лемма<br />
|about=2<br />
|statement=<br />
Пусть <tex>G = (N, \Sigma, P, S)</tex> {{---}} однозначная КС-грамматика без непорождающих нетерминалов и <tex>a_1 \dots a_n</tex> {{---}} цепочка из <tex>\Sigma^*</tex>. Тогда алгоритм Эрли пытается включить <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> в <tex>I_j</tex> не более одного раза, если <tex>\alpha \ne \varepsilon</tex>.<br />
|proof=<br />
Ситуацию <tex>[A \rightarrow \alpha \cdot \beta, i]</tex> можно включить в <tex>I_j</tex> только по правилам <tex>(1)</tex> (если последний символ <tex>\alpha</tex> — терминал) и <tex>(2)</tex> (если нетерминал). В первом случае результат очевиден. Во втором случае допустим, что <tex>[A \rightarrow \alpha'B \cdot \beta, i]</tex> включается в <tex>I_j</tex>, когда рассматриваются две ситуации <tex>[B \rightarrow \eta_1 \cdot, k_1]</tex> и <tex>[B \rightarrow \eta_2 \cdot, k_2]</tex> (они различны, так как в цикле <tex>(*)</tex> каждая ситуация из каждого списка рассматривается по одному разу). Тогда ситуация <tex>[A \rightarrow \alpha' \cdot B\beta, i]</tex> должна оказаться одновременно в <tex>I_{k_1}</tex> и в <tex>I_{k_2}</tex>. Таким образом, получаем:<br />
* <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex> и <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>;<br />
* <tex>\eta_1 \Rightarrow^* a_{k_1+1} \ldots a_j</tex> и <tex>\eta_2 \Rightarrow^* a_{k_2+1} \ldots a_j</tex>.<br />
Следовательно, <tex>\alpha' \eta_1 \Rightarrow^* a_{i+1} \ldots a_j</tex> и <tex>\alpha' \eta_2 \Rightarrow^* a_{i+1} \ldots a_j</tex>.<br/><br />
Заметим, что <tex>S \Rightarrow^* \gamma A \delta \Rightarrow^* a_1 \ldots a_i A \delta \Rightarrow a_1 \ldots a_i \alpha' B \beta \delta</tex>. Предположим, что <tex>\beta \delta \Rightarrow^* w'</tex> (ведь в грамматике нет непорождающих нетерминалов). Тогда <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_1 w'</tex> и аналогично <tex>S \Rightarrow^* a_1 \ldots a_i \alpha' \eta_2 w'</tex>.<br/><br />
Таким образом, если <tex>k_1 \ne k_2</tex>, то подстрока <tex>a_{i+1} \ldots a_j</tex> выводится двумя различными способами из <tex>\alpha' \eta_1</tex> и <tex>\alpha' \eta_2</tex> (поскольку в первом случае <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_1}</tex>, а во втором <tex>\alpha' \Rightarrow^* a_{i+1} \ldots a_{k_2}</tex>), то есть у строки <tex>a_1 \ldots a_jw'</tex> есть два различных вывода, что противоречит однозначности грамматики. Если же <tex>k_1 = k_2</tex>, то <tex>\eta_1 \ne \eta_2</tex>, что приводит к аналогичному противоречию.<br />
}}<br />
<br />
<br />
{{Теорема<br />
|statement=<br />
Если входная грамматика однозначна, то время выполнения алгоритма Эрли для слова длины <tex>n</tex> составляет <tex>O(n^2)</tex>.<br />
|proof=<br />
Орагнизуем каждый список разбора <tex>I_j</tex> таким образом, чтобы по любому символу <tex>x \in \Sigma \cup N</tex>, можно было за <tex>O(1)</tex> получить список тех и только тех ситуаций, содержащихся в <tex>I_j</tex>, которые имеют вид <tex>[A \rightarrow \alpha \cdot x \beta, j]</tex>.<br />
<br />
Время построения <tex>I_0</tex> не зависит от входной строки.<br />
<br />
Рассмотрим <tex>I_j, \, j > 0</tex>.<br />
# При включении ситуаций по правилу <tex>(1)</tex> необходимо лишь просмотреть предыдущий список и для каждого его элемента выполнить константное число операций.<br />
# Рассмотрим правило <tex>(2)</tex>. Можно считать, что внутри цикла <tex>(*)</tex> рассматриваются те и только те ситуации, которые удовлетворяют условию (так как список таких ситуаций можно по нетерминалу получить за <tex>O(1)</tex>). Тогда каждая такая ситуация будет добавлена в список и, исходя из леммы 2, попытка добавления будет единственной. А так как по лемме 1 всего в списке <tex>I_j</tex> находится <tex>O(j)</tex> ситуаций, то суммарно за все итерации внешнего цикла while внутри цикла <tex>(*)</tex> будет рассмотрено <tex>O(j)</tex> ситуаций.<br />
# Так как грамматика фиксирована, то при применении правила <tex>(3)</tex> при рассмотрении любой ситуации количество включаемых ситуаций не превосходит некоторой константы, поэтому для каждой рассмотренной ситуации будет выполнено <tex>O(1)</tex> операций.<br />
Таким образом, на построение списка <tex>I_j</tex> будет потрачено <tex>O(j)</tex> операций. Тогда время работы алгоритма составляет <tex>O(n^2)</tex>.<br />
}}<br />
<br />
== См. также ==<br />
* [[Алгоритм_Эрли | Алгоритм Эрли]]<br />
* [[Алгоритм_Кока-Янгера-Касами_разбора_грамматики_в_НФХ | Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ ]]<br />
<br />
== Источники информации==<br />
*А. Ахо, Дж. Ульман. Теория синтакcического анализа, перевода и компиляции. Том 1. Синтакcический анализ.<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58690Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-04T18:20:23Z<p>Zernov: /* Обычный вариант */</p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]]. Кроме того, построение регулярного выражения таким образом обычно гораздо проще (выполняется за меньшее количество шагов).<br />
<br />
== Пример ==<br />
=== Система уравнений ===<br />
[[Файл:at_least_one_zero.png|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел, в которых есть хотя бы один ноль. Для этого составим уравнение, добавляя соответствующие переменные в правую часть при наличии перехода по символу, а так же <tex>\varepsilon</tex> для терминального состояния, как это указано в доказательстве. <br />
<br />
<tex><br />
\begin{cases}<br />
L_1 = 1L_1\\<br />
L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon <br />
\end{cases}<br />
</tex><br />
<br />
Найдем <tex> L_1 </tex>:<br />
<br />
<tex>L_1 = 1L_1</tex>.<br />
<br />
Так как <tex> \varepsilon \notin 1 </tex>, то <tex>L_1 = 1^*</tex>.<br />
<br />
Выразим <tex> L_2 </tex> через <tex> L_1 </tex>:<br />
<br />
<tex>L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon</tex><br />
<br />
Откуда <tex>L_2 = 01^* (0 + 1)^*</tex>.<br />
<br />
=== Обычный вариант ===<br />
<br />
Теперь найдем регулярное выражение для этого же автомата с помощью теоремы Клини (обычный вариант).<br />
Для начала построим таблицу, согласно [[Теорема_Клини_(совпадение_классов_автоматных_и_регулярных_языков) | теореме]] по шагам:<br />
<br />
{| border="1" class="wikitable" style="width: 250px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Значения<br />
|-<br />
|<tex>R_{11}^{(0)}</tex><br />
|<tex>\varepsilon + 1</tex><br />
|-<br />
|<tex>R_{12}^{(0)}</tex><br />
|<tex>0</tex><br />
|-<br />
|<tex>R_{21}^{(0)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(0)}</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Например, в выражении <tex>R_{11}^{(0)}</tex> присутствует член <tex>\varepsilon</tex>, потому что и начальным, и конечным является состояние <tex>1</tex>. Это выражение включает также <tex>1</tex>, поскольку существует путь<br />
из состояния <tex>1</tex> в состояние <tex>1</tex> по входу <tex>1</tex>. Выражение <tex>R_{12}^{(0)}</tex> равно <tex>0</tex>, потому что есть дуга с<br />
меткой <tex>0</tex>, ведущая из состояния <tex>1</tex> в состояние <tex>2</tex>. Здесь нет члена <tex>\varepsilon</tex>, поскольку начальное<br />
и конечное состояния различаются. И, наконец, <tex>R_{21}^{(0)} = \varnothing</tex>, так как нет путей, ведущих из<br />
состояния <tex>2</tex> в состояние <tex>1</tex>.<br />
Теперь применим индукцию для построения более сложных выражений. <br />
<br />
Правило для вычисления выражения <tex>R_{ij}^{(1)}</tex> представляет собой пример общего правила из части теоремы Клини:<br />
<br />
<tex>R_{ij}^{(1)} = R_{ij}^{(0)} + R_{i1}^{(0)} (R_{11}^{(0)})^* R_{1j}^{(0)}</tex><br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Прямая подстановка<br />
!style="background:#41aef0"|Упрощенное выражение<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>\varepsilon + 1 + (\varepsilon + 1)(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>0 + (\varepsilon + 1)(\varepsilon + 1)^*0</tex><br />
|<tex>1^*0</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing + \varnothing(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>\varepsilon + 0 + 1 + \varnothing(\varepsilon + 1)^*0</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
И, наконец, последний шаг индукции<br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение <br />
!style="background:#41aef0"|Упрощенное выражение (после подстановки)<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>1^*0(0 + 1)^*</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>(0 + 1)^*</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Окончательное регулярное выражение, эквивалентное автомату, строится путем объединения всех тех выражений, для которых первое состояние<br />
является начальным, а второе {{---}} заключительным. В нашем примере <tex>1</tex> {{---}} начальное состояние, а <tex>2</tex> {{---}} заключительное, поэтому нам нужно лишь выражение <tex>R_{12}^{(1)}</tex>, равное <tex>1^*0(0 + 1)^*</tex><br />
<br />
Отметим, что первый вариант значительно короче. Для решения системы уравнений необходимо выполнить <tex>O(n)</tex> итераций, где <tex>n</tex> {{---}} число вершин. В каждом уравнении в худшем случае может быть <tex>|\Gamma| \cdot (n - 1)</tex> переменных в правой части {{---}} все возможные переходы по всем возможным состояниям. Теперь, для решения вторым вариантом, нам во-первых надо построить массив размера <tex>|\Gamma| \cdot n</tex> для всех переходов из всех состояний и выполнить столько же итераций, поскольку самый длинный путь в худшем случае будет проходить по всем переходам из всех вершин с возвращением в исходную, которая и будет являться терминальной, то есть в итоге сложность <tex>O((|\Gamma| \cdot n)^2)</tex>. Кроме того, в алгоритме на каждом шаге мы упрощали выражение, чтобы оно было более коротким. В общем случае длина выражения перед упрощением трудно поддается оценке, однако не стоит забывать про этот факт. В случае, если выражение не будет упрощаться, то по приведенной выше формуле итерации, оно, очевидно, с каждой итерацией будет значительно (степенная зависимость) расти.<br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini Mathhelpplanet {{---}} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. {{---}} М.: Издательский дом «Вильямс», 2008. {{---}} С. 112 {{---}} ISBN 978-5-8459-1347-0 <br />
<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58679Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-04T17:56:42Z<p>Zernov: /* Пример */</p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]]. Кроме того, построение регулярного выражения таким образом обычно гораздо проще (выполняется за меньшее количество шагов).<br />
<br />
== Пример ==<br />
=== Система уравнений ===<br />
[[Файл:at_least_one_zero.png|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел, в которых есть хотя бы один ноль. Для этого составим уравнение, добавляя соответствующие переменные в правую часть при наличии перехода по символу, а так же <tex>\varepsilon</tex> для терминального состояния, как это указано в доказательстве. <br />
<br />
<tex><br />
\begin{cases}<br />
L_1 = 1L_1\\<br />
L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon <br />
\end{cases}<br />
</tex><br />
<br />
Найдем <tex> L_1 </tex>:<br />
<br />
<tex>L_1 = 1L_1</tex>.<br />
<br />
Так как <tex> \varepsilon \notin 1 </tex>, то <tex>L_1 = 1^*</tex>.<br />
<br />
Выразим <tex> L_2 </tex> через <tex> L_1 </tex>:<br />
<br />
<tex>L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon</tex><br />
<br />
Откуда <tex>L_2 = 01^* (0 + 1)^*</tex>.<br />
<br />
=== Обычный вариант ===<br />
<br />
Теперь найдем регулярное выражение для этого же автомата с помощью теоремы Клини (обычный вариант).<br />
Для начала построим таблицу, согласно [[Теорема_Клини_(совпадение_классов_автоматных_и_регулярных_языков) | теореме]] по шагам:<br />
<br />
{| border="1" class="wikitable" style="width: 250px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Значения<br />
|-<br />
|<tex>R_{11}^{(0)}</tex><br />
|<tex>\varepsilon + 1</tex><br />
|-<br />
|<tex>R_{12}^{(0)}</tex><br />
|<tex>0</tex><br />
|-<br />
|<tex>R_{21}^{(0)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(0)}</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Например, в выражении <tex>R_{11}^{(0)}</tex> присутствует член <tex>\varepsilon</tex>, потому что и начальным, и конечным является состояние <tex>1</tex>. Это выражение включает также <tex>1</tex>, поскольку существует путь<br />
из состояния <tex>1</tex> в состояние <tex>1</tex> по входу <tex>1</tex>. Выражение <tex>R_{12}^{(0)}</tex> равно <tex>0</tex>, потому что есть дуга с<br />
меткой <tex>0</tex>, ведущая из состояния <tex>1</tex> в состояние <tex>2</tex>. Здесь нет члена <tex>\varepsilon</tex>, поскольку начальное<br />
и конечное состояния различаются. И, наконец, <tex>R_{21}^{(0)} = \varnothing</tex>, так как нет путей, ведущих из<br />
состояния <tex>2</tex> в состояние <tex>1</tex>.<br />
Теперь применим индукцию для построения более сложных выражений. <br />
<br />
Правило для вычисления выражения <tex>R_{ij}^{(1)}</tex> представляет собой пример общего правила из части теоремы Клини:<br />
<br />
<tex>R_{ij}^{(1)} = R_{ij}^{(0)} + R_{i1}^{(0)} (R_{11}^{(0)})^* R_{1j}^{(0)}</tex><br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Прямая подстановка<br />
!style="background:#41aef0"|Упрощенное выражение<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>\varepsilon + 1 + (\varepsilon + 1)(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>0 + (\varepsilon + 1)(\varepsilon + 1)^*0</tex><br />
|<tex>1^*0</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing + \varnothing(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>\varepsilon + 0 + 1 + \varnothing(\varepsilon + 1)^*0</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
И, наконец, последний шаг индукции<br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение <br />
!style="background:#41aef0"|Упрощенное выражение (после подстановки)<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>1^*0(0 + 1)^*</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>(0 + 1)^*</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Окончательное регулярное выражение, эквивалентное автомату, строится путем объединения всех тех выражений, для которых первое состояние<br />
является начальным, а второе {{---}} заключительным. В нашем примере <tex>1</tex> {{---}} начальное состояние, а <tex>2</tex> {{---}} заключительное, поэтому нам нужно лишь выражение <tex>R_{12}^{(1)}</tex>, равное <tex>1^*0(0 + 1)^*</tex><br />
<br />
Отметим, что первый вариант значительно короче. Для решения системы уравнений необходимо выполнить <tex>O(n)</tex> итераций, где <tex>n</tex> {{---}} число вершин. В каждом уравнении в худшем случае может быть <tex>|\Gamma| \cdot (n - 1)</tex> переменных в правой части {{---}} все возможные переходы по всем возможным состояниям. Теперь, для решения вторым вариантом, нам во-первых надо построить массив размера <tex>|\Gamma| \cdot n</tex> для всех переходов из всех состояний и выполнить столько же итераций, поскольку самый длинный путь в худшем случае будет проходить по всем переходам из всех вершин с возвращением в исходную, которая и будет являться терминальной, то есть в итоге сложность <tex>O((|\Gamma| \cdot n)^2)</tex><br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini Mathhelpplanet {{---}} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. {{---}} М.: Издательский дом «Вильямс», 2008. {{---}} С. 112 {{---}} ISBN 978-5-8459-1347-0 <br />
<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%9E%D0%B3%D0%B4%D0%B5%D0%BD%D0%B0&diff=58645Лемма Огдена2017-01-04T17:12:27Z<p>Zernov: /* Пример не КС-языка, для которого выполняется лемма */</p>
<hr />
<div>== Лемма ==<br />
{{Лемма<br />
|statement=<br />
Для каждой [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободной грамматики]] <tex>\Gamma =\langle \Sigma, N, S \in N, P \subset N\times (\Sigma\cup N)^{*}\rangle</tex> существует такое <tex>n</tex>, что для любого слова <tex>\omega \in L(\Gamma)</tex> длины не менее <tex>n</tex> и для любых выделенных в <tex>\omega</tex> не менее <tex>n</tex> позиций, <tex>\omega</tex> может быть представлено в виде <tex>\omega=uvxyz</tex>, причем:<br />
# <tex>x</tex> содержит выделенную позицию;<br />
# либо <tex>u</tex> и <tex>v</tex>, либо <tex>y</tex> и <tex>z</tex> обе содержат выделенные позиции;<br />
# <tex>vxy</tex> содержат не более <tex>n</tex> выделенных позиций;<br />
# существует <tex>A \in N</tex>, такой что <tex>S \Rightarrow^{+} uAz \Rightarrow^{+} uvAyz \Rightarrow^{+} uvxyz</tex>. (т.е. <tex>\forall k \geqslant 0~uv^{k}xy^{k}z\in L</tex>)<br />
|proof=<br />
Введем следующие обозначения: <tex>m = |N|</tex> и <tex>l</tex> — длина самой длинной правой части правила из <tex>P</tex>. Тогда в качестве <tex>n</tex> возьмем <tex>l^{2m + 3}</tex>. Рассмотрим дерево разбора <tex>T</tex> для произвольного слова <tex>\omega \in L(\Gamma)</tex>, у которого <tex>|\omega| \ge n</tex>. В силу выбора <tex>n</tex> в <tex>T</tex> будет по крайне мере один путь от корня до листа длины не менее <tex>2m + 3</tex>. Произвольным образом выделим в <tex>\omega</tex> не менее <tex>n</tex> позиций. Соответствующие этим позициям листья дерева <tex>T</tex> будем называть выделенными.<br />
<br />
Пусть <tex>v_1</tex> — корень <tex>T</tex>, а <tex>v_{i + 1}</tex> — сын <tex>v_i</tex>, который имеет среди своих потомков наибольшее число выделенных листьев (если таких несколько, то <tex>v_{i + 1}</tex> самый правый из них). Рассмотрим <tex>v_1, v_2, ..., v_p</tex> — путь от корня до листа. <br />
<br />
Будем называть ветвящейся ту вершину, у которой по крайне мере два сына имеют выделенных потомков. Докажем по индукции, что если среди <tex>v_1, v_2, ..., v_i</tex> вершин есть <tex>k</tex> ветвящихся, то <tex>v_{i + 1}</tex> имеет хотя бы <tex>l^{2m + 3 - k}</tex> выделенных потомков. <br>База индукции: <tex>i = 0</tex>. Тогда <tex>k = 0</tex> и <tex>v_1</tex> имеет по крайне мере <tex>n</tex> выделенных потомков, поскольку является корнем. <br>Индукционный переход. Если <tex>v_i</tex> не является ветвящейся вершиной, то <tex>v_{i + 1}</tex> имеет такое же число ветвящихся потомков, как и <tex>v_i</tex>. Если <tex>v_i</tex> — ветвящаяся вершина, то <tex>v_{i + 1}</tex> имеет не более чем в <tex>l</tex> раз меньшее число выделенных потомков.<br />
<br />
Поскольку <tex>v_1</tex> имеет хотя бы <tex>n = l^{2m + 3}</tex> выделенных потомков, то <tex>v_1, v_2, ..., v_p</tex> содержит по крайне мере <tex>2m + 3</tex> ветвящиеся вершин. Заметим, что <tex>v_p</tex> — лист, поэтому <tex>p > 2m + 3</tex>.<br />
<br />
[[Файл:derivation_tree_T.png|240px|thumb|left|Дерево вывода <tex>T</tex>]]Будем называть <tex>v_i</tex> левой ветвящейся вершиной, если ее сын, не принадлежащий пути <tex>v_1, v_2, ..., v_p</tex>, имеет выделенного потомка, лежащего слева от <tex>v_p</tex>. В противном случае назовем <tex>v_i</tex> правой ветвящейся вершиной. Рассмотрим последние <tex>2m + 3</tex> вершины, принадлежащие пути <tex>v_1, v_2, ..., v_p</tex>. Предположим, что хотя бы <tex>m + 2</tex> вершины {{---}} левые ветвящиеся (случай, когда хотя бы <tex>m + 2</tex> вершины {{---}} правые ветвящиеся, разбирается аналогично). Пусть <tex>u_1, u_2, ..., u_{m + 2}</tex> — последние <tex>m + 2</tex> левые ветвящиеся вершины. Поскольку <tex>m = |N|</tex>, то среди них можно найти как минимум две вершины, соответствующие одному нетерминалу. Обозначим эти вершины <tex>a</tex> и <tex>b</tex>, причем <tex>b</tex> {{---}} потомок <tex>a</tex>. Тогда на рисунке показано, как представить <tex>\omega</tex> в требуемом виде.<br />
<br />
<br />
Условие (1) выполнено, поскольку <tex>x</tex> содержит выделенную вершину, а именно <tex>v_p</tex>. Очевидно, что условие (4) выполнено в силу предложенного разбиения <tex>\omega</tex>. Кроме того, <tex>u</tex> содержит выделенную вершину, а именно потомка некоторого сына вершины <tex>u_1</tex>. Аналогично, выделенный потомок некоторого сына вершины <tex>a</tex> содержится в <tex>v</tex>. Таким образом, условие (2) выполнено. Поскольку между <tex>v_p</tex> и <tex>a</tex> не более <tex>2m + 3</tex> вершин, вершина <tex>a</tex> имеет не более <tex>n</tex> выделенных потомков, поэтому условие (3) выполнено.<br />
}}<br />
<br />
== Пример не КС-языка, для которого выполняется лемма ==<br />
Докажем, что можно построить такой язык, для которого будет выполняться лемма Огдена, однако он не будет контекстно-свободным. Выберем <tex>P</tex> {{---}} подмножество <tex>N</tex> и <br />
<br />
<tex>A_{p} = \{ (ab)^n \mid P \in N \} </tex><br />
<br />
<tex>B_{p} = A_{p} \cup X^* \{aa, bb\}X^*</tex><br />
<br />
Языки над <tex>X=\{a, b\}</tex>.<br />
<br />
Очевидно, что <tex>B_{p}</tex> {{---}} КС, если <tex>A_{p}</tex> контекстно-свободен. <tex>B_{p}</tex> является рекурсивно-перечислимым, если и <tex>A_{p}</tex> им является. <br />
<br />
Для <tex>B_{p}</tex> будет выполняться лемма Огдена для <tex>n = 4</tex>. Выбрав <tex>A_{p}</tex> таким образом, чтобы он был рекурсивно-перечислимым, мы создадим такой язык. (Такие языки существуют)<ref><A.V. Aho & J.D. Ullman, The Theory of Parsing, Translation and Compilimg, Vol. I, 1972</ref><br />
<br />
== См. также ==<br />
[[Лемма_о_разрастании_для_КС-грамматик|Лемма о разрастании для КС-грамматик]]<br />
<br />
==Примечания==<br />
<br />
<references /><br />
<br />
== Источники ==<br />
<br />
*Hopcroft, Motwani and Ullman {{---}} Automata Theory, Languages, and Computation {{---}} Addison-Wesley, 1979. ISBN 81-7808-347-7.<br />
*Ogden, W. (1968). "A helpful result for proving inherent ambiguity". Mathematical Systems Theory. 2 (3): 191–194.<br />
*[http://archive.numdam.org/ARCHIVE/ITA/ITA_1978__12_3/ITA_1978__12_3_201_0/ITA_1978__12_3_201_0.pdf On languages satisfying Ogden's lemma]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58643Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-04T17:10:00Z<p>Zernov: /* Обычный вариант */</p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]]. Кроме того, построение регулярного выражения таким образом обычно гораздо проще (выполняется за меньшее количество шагов).<br />
<br />
== Пример ==<br />
=== Система уравнений ===<br />
[[Файл:at_least_one_zero.png|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел, в которых есть хотя бы один ноль. Для этого составим уравнение, добавляя соответствующие переменные в правую часть при наличии перехода по символу, а так же <tex>\varepsilon</tex> для терминального состояния, как это указано в доказательстве. <br />
<br />
<tex><br />
\begin{cases}<br />
L_1 = 1L_1\\<br />
L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon <br />
\end{cases}<br />
</tex><br />
<br />
Найдем <tex> L_1 </tex>:<br />
<br />
<tex>L_1 = 1L_1</tex>.<br />
<br />
Так как <tex> \varepsilon \notin 1 </tex>, то <tex>L_1 = 1^*</tex>.<br />
<br />
Выразим <tex> L_2 </tex> через <tex> L_1 </tex>:<br />
<br />
<tex>L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon</tex><br />
<br />
Откуда <tex>L_2 = 01^* (0 + 1)^*</tex>.<br />
<br />
=== Обычный вариант ===<br />
<br />
Теперь найдем регулярное выражение для этого же автомата с помощью теоремы Клини (обычный вариант).<br />
Для начала построим таблицу, согласно [[Теорема_Клини_(совпадение_классов_автоматных_и_регулярных_языков) | теореме]] по шагам:<br />
<br />
{| border="1" class="wikitable" style="width: 250px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Значения<br />
|-<br />
|<tex>R_{11}^{(0)}</tex><br />
|<tex>\varepsilon + 1</tex><br />
|-<br />
|<tex>R_{12}^{(0)}</tex><br />
|<tex>0</tex><br />
|-<br />
|<tex>R_{21}^{(0)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(0)}</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Например, в выражении <tex>R_{11}^{(0)}</tex> присутствует член <tex>\varepsilon</tex>, потому что и начальным, и конечным является состояние <tex>1</tex>. Это выражение включает также <tex>1</tex>, поскольку существует путь<br />
из состояния <tex>1</tex> в состояние <tex>1</tex> по входу <tex>1</tex>. Выражение <tex>R_{12}^{(0)}</tex> равно <tex>0</tex>, потому что есть дуга с<br />
меткой <tex>0</tex>, ведущая из состояния <tex>1</tex> в состояние <tex>2</tex>. Здесь нет члена <tex>\varepsilon</tex>, поскольку начальное<br />
и конечное состояния различаются. И, наконец, <tex>R_{21}^{(0)} = \varnothing</tex>, так как нет путей, ведущих из<br />
состояния <tex>2</tex> в состояние <tex>1</tex>.<br />
Теперь применим индукцию для построения более сложных выражений. <br />
<br />
Правило для вычисления выражения <tex>R_{ij}^{(1)}</tex> представляет собой пример общего правила из части теоремы Клини:<br />
<br />
<tex>R_{ij}^{(1)} = R_{ij}^{(0)} + R_{i1}^{(0)} (R_{11}^{(0)})^* R_{1j}^{(0)}</tex><br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Прямая подстановка<br />
!style="background:#41aef0"|Упрощенное выражение<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>\varepsilon + 1 + (\varepsilon + 1)(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>0 + (\varepsilon + 1)(\varepsilon + 1)^*0</tex><br />
|<tex>1^*0</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing + \varnothing(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>\varepsilon + 0 + 1 + \varnothing(\varepsilon + 1)^*0</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
И, наконец, последний шаг индукции<br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Упрощенное выражение (после подстановки)<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>1^*0(0 + 1)^*</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>(0 + 1)^*</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Окончательное регулярное выражение, эквивалентное автомату, строится путем объединения всех тех выражений, для которых первое состояние<br />
является начальным, а второе {{---}} заключительным. В нашем примере <tex>1</tex> {{---}} начальное состояние, а <tex>2</tex> {{---}} заключительное, поэтому нам нужно лишь выражение <tex>R_{12}^{(1)}</tex>, равное <tex>1^*0(0 + 1)^*</tex><br />
<br />
Отметим, что первый вариант значительно короче. В общем случае, обычно проще решить систему уравнений, чем выполнять несколько итераций. Учитывая, что количество итераций увеличивается с увеличением переходов в автомате (мы ищем все варианты прохода в терминальное состояние), то даже в автомате из трех состояний количество итераций может быть достаточно большим.<br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini Mathhelpplanet {{---}} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. {{---}} М.: Издательский дом «Вильямс», 2008. {{---}} С. 112 {{---}} ISBN 978-5-8459-1347-0 <br />
<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58642Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-04T17:09:30Z<p>Zernov: /* Система уравнений */</p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]]. Кроме того, построение регулярного выражения таким образом обычно гораздо проще (выполняется за меньшее количество шагов).<br />
<br />
== Пример ==<br />
=== Система уравнений ===<br />
[[Файл:at_least_one_zero.png|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел, в которых есть хотя бы один ноль. Для этого составим уравнение, добавляя соответствующие переменные в правую часть при наличии перехода по символу, а так же <tex>\varepsilon</tex> для терминального состояния, как это указано в доказательстве. <br />
<br />
<tex><br />
\begin{cases}<br />
L_1 = 1L_1\\<br />
L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon <br />
\end{cases}<br />
</tex><br />
<br />
Найдем <tex> L_1 </tex>:<br />
<br />
<tex>L_1 = 1L_1</tex>.<br />
<br />
Так как <tex> \varepsilon \notin 1 </tex>, то <tex>L_1 = 1^*</tex>.<br />
<br />
Выразим <tex> L_2 </tex> через <tex> L_1 </tex>:<br />
<br />
<tex>L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon</tex><br />
<br />
Откуда <tex>L_2 = 01^* (0 + 1)^*</tex>.<br />
<br />
=== Обычный вариант ===<br />
<br />
Теперь найдем регулярное выражение для этого же автомата с помощью теоремы Клини (обычный вариант).<br />
Для начала построим таблицу, согласно [[Теорема_Клини_(совпадение_классов_автоматных_и_регулярных_языков) | теореме]] по шагам:<br />
<br />
{| border="1" class="wikitable" style="width: 250px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Значения<br />
|-<br />
|<tex>R_{11}^{(0)}</tex><br />
|<tex>\varepsilon + 1</tex><br />
|-<br />
|<tex>R_{12}^{(0)}</tex><br />
|<tex>0</tex><br />
|-<br />
|<tex>R_{21}^{(0)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(0)}</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Например, в выражении <tex>R_{11}^{(0)}</tex> присутствует член <tex>\varepsilon</tex>, потому что и начальным, и конечным является состояние <tex>1</tex>. Это выражение включает также <tex>1</tex>, поскольку существует путь<br />
из состояния <tex>1</tex> в состояние <tex>1</tex> по входу <tex>1</tex>. Выражение <tex>R_{12}^{(0)}</tex> равно <tex>0</tex>, потому что есть дуга с<br />
меткой <tex>0</tex>, ведущая из состояния <tex>1</tex> в состояние <tex>2</tex>. Здесь нет члена <tex>\varepsilon</tex>, поскольку начальное<br />
и конечное состояния различаются. И, наконец, <tex>R_{21}^{(0)} = \varnothing</tex>, так как нет путей, ведущих из<br />
состояния <tex>2</tex> в состояние <tex>1</tex>.<br />
Теперь применим индукцию для построения более сложных выражений. <br />
<br />
Правило для вычисления выражения <tex>R_{ij}^{(1)}</tex> представляет собой пример общего правила из части теоремы Клини:<br />
<br />
<tex>R_{ij}^{(1)} = R_{ij}^{(0)} + R_{i1}^{(0)} (R_{11}^{(0)})^* R_{1j}^{(0)}</tex><br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Прямая подстановка<br />
!style="background:#41aef0"|Упрощенное выражение<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>\varepsilon + 1 + (\varepsilon + 1)(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>0 + (\varepsilon + 1)(\varepsilon + 1)^*0</tex><br />
|<tex>1^*0</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing + \varnothing(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>\varepsilon + 0 + 1 + \varnothing(\varepsilon + 1)^*0</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
И, наконец, последний шаг индукции<br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Упрощенное выражение (после подстановки)<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>1^*0(0 + 1)^*</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>(0 + 1)^*</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Окончательное регулярное выражение, эквивалентное автомату, строится путем объединения всех тех выражений, для которых первое состояние<br />
является начальным, а второе {{---}} заключительным. В нашем примере <tex>1</tex> {{---}} начальное состояние, а <tex>2</tex> {{---}} заключительное, поэтому нам нужно лишь выражение <tex>R_{12}^{(1)}</tex>, равное <tex>1^*0(0 + 1)^*</tex><br />
<br />
Отметим, что первый вариант значительно короче. В общем случае, обычно проще решить систему уравнений, чем выполнять несколько итераций. Учитывая, что количество итераций увеличивается с увеличением переходов в автомате (мы ищем все варианты прохода в финальное состояние), то даже в автомате из трех состояний количество итераций может быть достаточно большим.<br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini Mathhelpplanet {{---}} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. {{---}} М.: Издательский дом «Вильямс», 2008. {{---}} С. 112 {{---}} ISBN 978-5-8459-1347-0 <br />
<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58641Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-04T17:06:44Z<p>Zernov: /* Пример */</p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]]. Кроме того, построение регулярного выражения таким образом обычно гораздо проще (выполняется за меньшее количество шагов).<br />
<br />
== Пример ==<br />
=== Система уравнений ===<br />
[[Файл:at_least_one_zero.png|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел, в которых есть хотя бы один ноль<br />
<br />
<tex><br />
\begin{cases}<br />
L_1 = 1L_1\\<br />
L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon <br />
\end{cases}<br />
</tex><br />
<br />
Найдем <tex> L_1 </tex>:<br />
<br />
<tex>L_1 = 1L_1</tex>.<br />
<br />
Так как <tex> \varepsilon \notin 1 </tex>, то <tex>L_1 = 1^*</tex>.<br />
<br />
Выразим <tex> L_2 </tex> через <tex> L_1 </tex>:<br />
<br />
<tex>L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon</tex><br />
<br />
Откуда <tex>L_2 = 01^* (0 + 1)^*</tex>.<br />
<br />
=== Обычный вариант ===<br />
<br />
Теперь найдем регулярное выражение для этого же автомата с помощью теоремы Клини (обычный вариант).<br />
Для начала построим таблицу, согласно [[Теорема_Клини_(совпадение_классов_автоматных_и_регулярных_языков) | теореме]] по шагам:<br />
<br />
{| border="1" class="wikitable" style="width: 250px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Значения<br />
|-<br />
|<tex>R_{11}^{(0)}</tex><br />
|<tex>\varepsilon + 1</tex><br />
|-<br />
|<tex>R_{12}^{(0)}</tex><br />
|<tex>0</tex><br />
|-<br />
|<tex>R_{21}^{(0)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(0)}</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Например, в выражении <tex>R_{11}^{(0)}</tex> присутствует член <tex>\varepsilon</tex>, потому что и начальным, и конечным является состояние <tex>1</tex>. Это выражение включает также <tex>1</tex>, поскольку существует путь<br />
из состояния <tex>1</tex> в состояние <tex>1</tex> по входу <tex>1</tex>. Выражение <tex>R_{12}^{(0)}</tex> равно <tex>0</tex>, потому что есть дуга с<br />
меткой <tex>0</tex>, ведущая из состояния <tex>1</tex> в состояние <tex>2</tex>. Здесь нет члена <tex>\varepsilon</tex>, поскольку начальное<br />
и конечное состояния различаются. И, наконец, <tex>R_{21}^{(0)} = \varnothing</tex>, так как нет путей, ведущих из<br />
состояния <tex>2</tex> в состояние <tex>1</tex>.<br />
Теперь применим индукцию для построения более сложных выражений. <br />
<br />
Правило для вычисления выражения <tex>R_{ij}^{(1)}</tex> представляет собой пример общего правила из части теоремы Клини:<br />
<br />
<tex>R_{ij}^{(1)} = R_{ij}^{(0)} + R_{i1}^{(0)} (R_{11}^{(0)})^* R_{1j}^{(0)}</tex><br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Прямая подстановка<br />
!style="background:#41aef0"|Упрощенное выражение<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>\varepsilon + 1 + (\varepsilon + 1)(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>0 + (\varepsilon + 1)(\varepsilon + 1)^*0</tex><br />
|<tex>1^*0</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing + \varnothing(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>\varepsilon + 0 + 1 + \varnothing(\varepsilon + 1)^*0</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
И, наконец, последний шаг индукции<br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Упрощенное выражение (после подстановки)<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>1^*0(0 + 1)^*</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>(0 + 1)^*</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Окончательное регулярное выражение, эквивалентное автомату, строится путем объединения всех тех выражений, для которых первое состояние<br />
является начальным, а второе {{---}} заключительным. В нашем примере <tex>1</tex> {{---}} начальное состояние, а <tex>2</tex> {{---}} заключительное, поэтому нам нужно лишь выражение <tex>R_{12}^{(1)}</tex>, равное <tex>1^*0(0 + 1)^*</tex><br />
<br />
Отметим, что первый вариант значительно короче. В общем случае, обычно проще решить систему уравнений, чем выполнять несколько итераций. Учитывая, что количество итераций увеличивается с увеличением переходов в автомате (мы ищем все варианты прохода в финальное состояние), то даже в автомате из трех состояний количество итераций может быть достаточно большим.<br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini Mathhelpplanet {{---}} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. {{---}} М.: Издательский дом «Вильямс», 2008. {{---}} С. 112 {{---}} ISBN 978-5-8459-1347-0 <br />
<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58640Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-04T17:01:12Z<p>Zernov: </p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]]. Кроме того, построение регулярного выражения таким образом обычно гораздо проще (выполняется за меньшее количество шагов).<br />
<br />
== Пример ==<br />
=== Система уравнений ===<br />
[[Файл:at_least_one_zero.png|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел, в которых есть хотя бы один ноль<br />
<br />
<tex><br />
\begin{cases}<br />
L_1 = 1L_1\\<br />
L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon <br />
\end{cases}<br />
</tex><br />
<br />
Найдем <tex> L_1 </tex>:<br />
<br />
<tex>L_1 = 1L_1</tex>.<br />
<br />
Так как <tex> \varepsilon \notin 1 </tex>, то <tex>L_1 = 1^*</tex>.<br />
<br />
Выразим <tex> L_2 </tex> через <tex> L_1 </tex>:<br />
<br />
<tex>L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon</tex><br />
<br />
Откуда <tex>L_2 = 01^* (0 + 1)^*</tex>.<br />
<br />
=== Обычный вариант ===<br />
<br />
Теперь найдем регулярное выражение для этого же автомата с помощью теоремы Клини (обычный вариант).<br />
Для начала построим таблицу, согласно [[Теорема_Клини_(совпадение_классов_автоматных_и_регулярных_языков) | теореме]] по шагам:<br />
<br />
{| border="1" class="wikitable" style="width: 250px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Значения<br />
|-<br />
|<tex>R_{11}^{(0)}</tex><br />
|<tex>\varepsilon + 1</tex><br />
|-<br />
|<tex>R_{12}^{(0)}</tex><br />
|<tex>0</tex><br />
|-<br />
|<tex>R_{21}^{(0)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(0)}</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Например, в выражении <tex>R_{11}^{(0)}</tex> присутствует член <tex>\varepsilon</tex>, потому что и начальным, и конечным является состояние <tex>1</tex>. Это выражение включает также <tex>1</tex>, поскольку существует путь<br />
из состояния <tex>1</tex> в состояние <tex>1</tex> по входу <tex>1</tex>. Выражение <tex>R_{12}^{(0)}</tex> равно <tex>0</tex>, потому что есть дуга с<br />
меткой <tex>0</tex>, ведущая из состояния <tex>1</tex> в состояние <tex>2</tex>. Здесь нет члена <tex>\varepsilon</tex>, поскольку начальное<br />
и конечное состояния различаются. И, наконец, <tex>R_{21}^{(0)} = \varnothing</tex>, так как нет путей, ведущих из<br />
состояния <tex>2</tex> в состояние <tex>1</tex>.<br />
Теперь применим индукцию для построения более сложных выражений. <br />
<br />
Правило для вычисления выражения <tex>R_{ij}^{(1)}</tex> представляет собой пример общего правила из части теоремы Клини:<br />
<br />
<tex>R_{ij}^{(1)} = R_{ij}^{(0)} + R_{i1}^{(0)} (R_{11}^{(0)})^* R_{1j}^{(0)}</tex><br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Прямая подстановка<br />
!style="background:#41aef0"|Упрощенное выражение<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>\varepsilon + 1 + (\varepsilon + 1)(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>0 + (\varepsilon + 1)(\varepsilon + 1)^*0</tex><br />
|<tex>1^*0</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing + \varnothing(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>\varepsilon + 0 + 1 + \varnothing(\varepsilon + 1)^*0</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
И, наконец, последний шаг индукции<br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Упрощенное выражение (после подстановки)<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>1^*0(0 + 1)^*</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>(0 + 1)^*</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Окончательное регулярное выражение, эквивалентное автомату, строится путем объединения всех тех выражений, для которых первое состояние<br />
является начальным, а второе {{---}} заключительным. В нашем примере <tex>1</tex> {{---}} начальное состояние, а <tex>2</tex> {{---}} заключительное, поэтому нам нужно лишь выражение <tex>R_{12}^{(1)}</tex>, равное <tex>1^*0(0 + 1)^*</tex><br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini Mathhelpplanet {{---}} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. {{---}} М.: Издательский дом «Вильямс», 2008. {{---}} С. 112 {{---}} ISBN 978-5-8459-1347-0 <br />
<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%9E%D0%B3%D0%B4%D0%B5%D0%BD%D0%B0&diff=58618Лемма Огдена2017-01-03T20:46:32Z<p>Zernov: </p>
<hr />
<div>== Лемма ==<br />
{{Лемма<br />
|statement=<br />
Для каждой [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободной грамматики]] <tex>\Gamma =\langle \Sigma, N, S \in N, P \subset N\times (\Sigma\cup N)^{*}\rangle</tex> существует такое <tex>n</tex>, что для любого слова <tex>\omega \in L(\Gamma)</tex> длины не менее <tex>n</tex> и для любых выделенных в <tex>\omega</tex> не менее <tex>n</tex> позиций, <tex>\omega</tex> может быть представлено в виде <tex>\omega=uvxyz</tex>, причем:<br />
# <tex>x</tex> содержит выделенную позицию;<br />
# либо <tex>u</tex> и <tex>v</tex>, либо <tex>y</tex> и <tex>z</tex> обе содержат выделенные позиции;<br />
# <tex>vxy</tex> содержат не более <tex>n</tex> выделенных позиций;<br />
# существует <tex>A \in N</tex>, такой что <tex>S \Rightarrow^{+} uAz \Rightarrow^{+} uvAyz \Rightarrow^{+} uvxyz</tex>. (т.е. <tex>\forall k \geqslant 0~uv^{k}xy^{k}z\in L</tex>)<br />
|proof=<br />
Введем следующие обозначения: <tex>m = |N|</tex> и <tex>l</tex> — длина самой длинной правой части правила из <tex>P</tex>. Тогда в качестве <tex>n</tex> возьмем <tex>l^{2m + 3}</tex>. Рассмотрим дерево разбора <tex>T</tex> для произвольного слова <tex>\omega \in L(\Gamma)</tex>, у которого <tex>|\omega| \ge n</tex>. В силу выбора <tex>n</tex> в <tex>T</tex> будет по крайне мере один путь от корня до листа длины не менее <tex>2m + 3</tex>. Произвольным образом выделим в <tex>\omega</tex> не менее <tex>n</tex> позиций. Соответствующие этим позициям листья дерева <tex>T</tex> будем называть выделенными.<br />
<br />
Пусть <tex>v_1</tex> — корень <tex>T</tex>, а <tex>v_{i + 1}</tex> — сын <tex>v_i</tex>, который имеет среди своих потомков наибольшее число выделенных листьев (если таких несколько, то <tex>v_{i + 1}</tex> самый правый из них). Рассмотрим <tex>v_1, v_2, ..., v_p</tex> — путь от корня до листа. <br />
<br />
Будем называть ветвящейся ту вершину, у которой по крайне мере два сына имеют выделенных потомков. Докажем по индукции, что если среди <tex>v_1, v_2, ..., v_i</tex> вершин есть <tex>k</tex> ветвящихся, то <tex>v_{i + 1}</tex> имеет хотя бы <tex>l^{2m + 3 - k}</tex> выделенных потомков. <br>База индукции: <tex>i = 0</tex>. Тогда <tex>k = 0</tex> и <tex>v_1</tex> имеет по крайне мере <tex>n</tex> выделенных потомков, поскольку является корнем. <br>Индукционный переход. Если <tex>v_i</tex> не является ветвящейся вершиной, то <tex>v_{i + 1}</tex> имеет такое же число ветвящихся потомков, как и <tex>v_i</tex>. Если <tex>v_i</tex> — ветвящаяся вершина, то <tex>v_{i + 1}</tex> имеет не более чем в <tex>l</tex> раз меньшее число выделенных потомков.<br />
<br />
Поскольку <tex>v_1</tex> имеет хотя бы <tex>n = l^{2m + 3}</tex> выделенных потомков, то <tex>v_1, v_2, ..., v_p</tex> содержит по крайне мере <tex>2m + 3</tex> ветвящиеся вершин. Заметим, что <tex>v_p</tex> — лист, поэтому <tex>p > 2m + 3</tex>.<br />
<br />
[[Файл:derivation_tree_T.png|240px|thumb|left|Дерево вывода <tex>T</tex>]]Будем называть <tex>v_i</tex> левой ветвящейся вершиной, если ее сын, не принадлежащий пути <tex>v_1, v_2, ..., v_p</tex>, имеет выделенного потомка, лежащего слева от <tex>v_p</tex>. В противном случае назовем <tex>v_i</tex> правой ветвящейся вершиной. Рассмотрим последние <tex>2m + 3</tex> вершины, принадлежащие пути <tex>v_1, v_2, ..., v_p</tex>. Предположим, что хотя бы <tex>m + 2</tex> вершины {{---}} левые ветвящиеся (случай, когда хотя бы <tex>m + 2</tex> вершины {{---}} правые ветвящиеся, разбирается аналогично). Пусть <tex>u_1, u_2, ..., u_{m + 2}</tex> — последние <tex>m + 2</tex> левые ветвящиеся вершины. Поскольку <tex>m = |N|</tex>, то среди них можно найти как минимум две вершины, соответствующие одному нетерминалу. Обозначим эти вершины <tex>a</tex> и <tex>b</tex>, причем <tex>b</tex> {{---}} потомок <tex>a</tex>. Тогда на рисунке показано, как представить <tex>\omega</tex> в требуемом виде.<br />
<br />
<br />
Условие (1) выполнено, поскольку <tex>x</tex> содержит выделенную вершину, а именно <tex>v_p</tex>. Очевидно, что условие (4) выполнено в силу предложенного разбиения <tex>\omega</tex>. Кроме того, <tex>u</tex> содержит выделенную вершину, а именно потомка некоторого сына вершины <tex>u_1</tex>. Аналогично, выделенный потомок некоторого сына вершины <tex>a</tex> содержится в <tex>v</tex>. Таким образом, условие (2) выполнено. Поскольку между <tex>v_p</tex> и <tex>a</tex> не более <tex>2m + 3</tex> вершин, вершина <tex>a</tex> имеет не более <tex>n</tex> выделенных потомков, поэтому условие (3) выполнено.<br />
}}<br />
<br />
== Пример не КС-языка, для которого выполняется лемма ==<br />
Докажем, что можно построить такой язык, для которого будет выполняться лемма Огдена, однако он не будет контекстно-свободным. Выберем <tex>P</tex> {{---}} подмножество <tex>N</tex> и <br />
<br />
<tex>A_{p} = \{ (ab)^n \mid P \in N \} </tex><br />
<br />
<tex>B_{p} = A_{p} \cup X^* \{aa, bb\}X^*</tex><br />
<br />
Языки над <tex>X=\{a, b\}</tex>.<br />
<br />
Очевидно, что <tex>B_{p}</tex> КС, если <tex>A_{p}</tex> контекстно-свободен. <tex>B_{p}</tex> является рекурсивно-перечислимым, если и <tex>A_{p}</tex> им является. <br />
<br />
Для <tex>B_{p}</tex> будет выполняться лемма Огдена для <tex>n = 4</tex>. Выбрав <tex>A_{p}</tex> таким образом, чтобы он был рекурсивно-перечислимым, мы создадим такой язык. (Такие языки существуют)<ref><A.V. Aho & J.D. Ullman, The Theory of Parsing, Translation and Compilimg, Vol. I, 1972</ref> <br />
<br />
== См. также ==<br />
[[Лемма_о_разрастании_для_КС-грамматик|Лемма о разрастании для КС-грамматик]]<br />
<br />
==Примечания==<br />
<br />
<references /><br />
<br />
== Источники ==<br />
<br />
*Hopcroft, Motwani and Ullman {{---}} Automata Theory, Languages, and Computation {{---}} Addison-Wesley, 1979. ISBN 81-7808-347-7.<br />
*Ogden, W. (1968). "A helpful result for proving inherent ambiguity". Mathematical Systems Theory. 2 (3): 191–194.<br />
*[http://archive.numdam.org/ARCHIVE/ITA/ITA_1978__12_3/ITA_1978__12_3_201_0/ITA_1978__12_3_201_0.pdf On languages satisfying Ogden's lemma]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%9E%D0%B3%D0%B4%D0%B5%D0%BD%D0%B0&diff=58617Лемма Огдена2017-01-03T20:45:52Z<p>Zernov: </p>
<hr />
<div>{{Лемма<br />
|statement=<br />
Для каждой [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободной грамматики]] <tex>\Gamma =\langle \Sigma, N, S \in N, P \subset N\times (\Sigma\cup N)^{*}\rangle</tex> существует такое <tex>n</tex>, что для любого слова <tex>\omega \in L(\Gamma)</tex> длины не менее <tex>n</tex> и для любых выделенных в <tex>\omega</tex> не менее <tex>n</tex> позиций, <tex>\omega</tex> может быть представлено в виде <tex>\omega=uvxyz</tex>, причем:<br />
# <tex>x</tex> содержит выделенную позицию;<br />
# либо <tex>u</tex> и <tex>v</tex>, либо <tex>y</tex> и <tex>z</tex> обе содержат выделенные позиции;<br />
# <tex>vxy</tex> содержат не более <tex>n</tex> выделенных позиций;<br />
# существует <tex>A \in N</tex>, такой что <tex>S \Rightarrow^{+} uAz \Rightarrow^{+} uvAyz \Rightarrow^{+} uvxyz</tex>. (т.е. <tex>\forall k \geqslant 0~uv^{k}xy^{k}z\in L</tex>)<br />
|proof=<br />
Введем следующие обозначения: <tex>m = |N|</tex> и <tex>l</tex> — длина самой длинной правой части правила из <tex>P</tex>. Тогда в качестве <tex>n</tex> возьмем <tex>l^{2m + 3}</tex>. Рассмотрим дерево разбора <tex>T</tex> для произвольного слова <tex>\omega \in L(\Gamma)</tex>, у которого <tex>|\omega| \ge n</tex>. В силу выбора <tex>n</tex> в <tex>T</tex> будет по крайне мере один путь от корня до листа длины не менее <tex>2m + 3</tex>. Произвольным образом выделим в <tex>\omega</tex> не менее <tex>n</tex> позиций. Соответствующие этим позициям листья дерева <tex>T</tex> будем называть выделенными.<br />
<br />
Пусть <tex>v_1</tex> — корень <tex>T</tex>, а <tex>v_{i + 1}</tex> — сын <tex>v_i</tex>, который имеет среди своих потомков наибольшее число выделенных листьев (если таких несколько, то <tex>v_{i + 1}</tex> самый правый из них). Рассмотрим <tex>v_1, v_2, ..., v_p</tex> — путь от корня до листа. <br />
<br />
Будем называть ветвящейся ту вершину, у которой по крайне мере два сына имеют выделенных потомков. Докажем по индукции, что если среди <tex>v_1, v_2, ..., v_i</tex> вершин есть <tex>k</tex> ветвящихся, то <tex>v_{i + 1}</tex> имеет хотя бы <tex>l^{2m + 3 - k}</tex> выделенных потомков. <br>База индукции: <tex>i = 0</tex>. Тогда <tex>k = 0</tex> и <tex>v_1</tex> имеет по крайне мере <tex>n</tex> выделенных потомков, поскольку является корнем. <br>Индукционный переход. Если <tex>v_i</tex> не является ветвящейся вершиной, то <tex>v_{i + 1}</tex> имеет такое же число ветвящихся потомков, как и <tex>v_i</tex>. Если <tex>v_i</tex> — ветвящаяся вершина, то <tex>v_{i + 1}</tex> имеет не более чем в <tex>l</tex> раз меньшее число выделенных потомков.<br />
<br />
Поскольку <tex>v_1</tex> имеет хотя бы <tex>n = l^{2m + 3}</tex> выделенных потомков, то <tex>v_1, v_2, ..., v_p</tex> содержит по крайне мере <tex>2m + 3</tex> ветвящиеся вершин. Заметим, что <tex>v_p</tex> — лист, поэтому <tex>p > 2m + 3</tex>.<br />
<br />
[[Файл:derivation_tree_T.png|240px|thumb|left|Дерево вывода <tex>T</tex>]]Будем называть <tex>v_i</tex> левой ветвящейся вершиной, если ее сын, не принадлежащий пути <tex>v_1, v_2, ..., v_p</tex>, имеет выделенного потомка, лежащего слева от <tex>v_p</tex>. В противном случае назовем <tex>v_i</tex> правой ветвящейся вершиной. Рассмотрим последние <tex>2m + 3</tex> вершины, принадлежащие пути <tex>v_1, v_2, ..., v_p</tex>. Предположим, что хотя бы <tex>m + 2</tex> вершины {{---}} левые ветвящиеся (случай, когда хотя бы <tex>m + 2</tex> вершины {{---}} правые ветвящиеся, разбирается аналогично). Пусть <tex>u_1, u_2, ..., u_{m + 2}</tex> — последние <tex>m + 2</tex> левые ветвящиеся вершины. Поскольку <tex>m = |N|</tex>, то среди них можно найти как минимум две вершины, соответствующие одному нетерминалу. Обозначим эти вершины <tex>a</tex> и <tex>b</tex>, причем <tex>b</tex> {{---}} потомок <tex>a</tex>. Тогда на рисунке показано, как представить <tex>\omega</tex> в требуемом виде.<br />
<br />
<br />
Условие (1) выполнено, поскольку <tex>x</tex> содержит выделенную вершину, а именно <tex>v_p</tex>. Очевидно, что условие (4) выполнено в силу предложенного разбиения <tex>\omega</tex>. Кроме того, <tex>u</tex> содержит выделенную вершину, а именно потомка некоторого сына вершины <tex>u_1</tex>. Аналогично, выделенный потомок некоторого сына вершины <tex>a</tex> содержится в <tex>v</tex>. Таким образом, условие (2) выполнено. Поскольку между <tex>v_p</tex> и <tex>a</tex> не более <tex>2m + 3</tex> вершин, вершина <tex>a</tex> имеет не более <tex>n</tex> выделенных потомков, поэтому условие (3) выполнено.<br />
}}<br />
<br />
== Пример не КС-языка, для которого выполняется лемма ==<br />
Докажем, что можно построить такой язык, для которого будет выполняться лемма Огдена, однако он не будет контекстно-свободным. Выберем <tex>P</tex> {{---}} подмножество <tex>N</tex> и <br />
<br />
<tex>A_{p} = \{ (ab)^n \mid P \in N \} </tex><br />
<br />
<tex>B_{p} = A_{p} \cup X^* \{aa, bb\}X^*</tex><br />
<br />
Языки над <tex>X=\{a, b\}</tex>.<br />
<br />
Очевидно, что <tex>B_{p}</tex> КС, если <tex>A_{p}</tex> контекстно-свободен. <tex>B_{p}</tex> является рекурсивно-перечислимым, если и <tex>A_{p}</tex> им является. <br />
<br />
Для <tex>B_{p}</tex> будет выполняться лемма Огдена для <tex>n = 4</tex>. Выбрав <tex>A_{p}</tex> таким образом, чтобы он был рекурсивно-перечислимым, мы создадим такой язык. (Такие языки существуют)<ref><A.V. Aho & J.D. Ullman, The Theory of Parsing, Translation and Compilimg, Vol. I, 1972</ref> <br />
<br />
== См. также ==<br />
[[Лемма_о_разрастании_для_КС-грамматик|Лемма о разрастании для КС-грамматик]]<br />
<br />
==Примечания==<br />
<br />
<references /><br />
<br />
== Источники ==<br />
<br />
*Hopcroft, Motwani and Ullman {{---}} Automata Theory, Languages, and Computation {{---}} Addison-Wesley, 1979. ISBN 81-7808-347-7.<br />
*Ogden, W. (1968). "A helpful result for proving inherent ambiguity". Mathematical Systems Theory. 2 (3): 191–194.<br />
*[http://archive.numdam.org/ARCHIVE/ITA/ITA_1978__12_3/ITA_1978__12_3_201_0/ITA_1978__12_3_201_0.pdf On languages satisfying Ogden's lemma]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%9E%D0%B3%D0%B4%D0%B5%D0%BD%D0%B0&diff=58616Лемма Огдена2017-01-03T20:43:03Z<p>Zernov: </p>
<hr />
<div>{{Лемма<br />
|statement=<br />
Для каждой [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободной грамматики]] <tex>\Gamma =\langle \Sigma, N, S \in N, P \subset N\times (\Sigma\cup N)^{*}\rangle</tex> существует такое <tex>n</tex>, что для любого слова <tex>\omega \in L(\Gamma)</tex> длины не менее <tex>n</tex> и для любых выделенных в <tex>\omega</tex> не менее <tex>n</tex> позиций, <tex>\omega</tex> может быть представлено в виде <tex>\omega=uvxyz</tex>, причем:<br />
# <tex>x</tex> содержит выделенную позицию;<br />
# либо <tex>u</tex> и <tex>v</tex>, либо <tex>y</tex> и <tex>z</tex> обе содержат выделенные позиции;<br />
# <tex>vxy</tex> содержат не более <tex>n</tex> выделенных позиций;<br />
# существует <tex>A \in N</tex>, такой что <tex>S \Rightarrow^{+} uAz \Rightarrow^{+} uvAyz \Rightarrow^{+} uvxyz</tex>. (т.е. <tex>\forall k \geqslant 0~uv^{k}xy^{k}z\in L</tex>)<br />
|proof=<br />
Введем следующие обозначения: <tex>m = |N|</tex> и <tex>l</tex> — длина самой длинной правой части правила из <tex>P</tex>. Тогда в качестве <tex>n</tex> возьмем <tex>l^{2m + 3}</tex>. Рассмотрим дерево разбора <tex>T</tex> для произвольного слова <tex>\omega \in L(\Gamma)</tex>, у которого <tex>|\omega| \ge n</tex>. В силу выбора <tex>n</tex> в <tex>T</tex> будет по крайне мере один путь от корня до листа длины не менее <tex>2m + 3</tex>. Произвольным образом выделим в <tex>\omega</tex> не менее <tex>n</tex> позиций. Соответствующие этим позициям листья дерева <tex>T</tex> будем называть выделенными.<br />
<br />
Пусть <tex>v_1</tex> — корень <tex>T</tex>, а <tex>v_{i + 1}</tex> — сын <tex>v_i</tex>, который имеет среди своих потомков наибольшее число выделенных листьев (если таких несколько, то <tex>v_{i + 1}</tex> самый правый из них). Рассмотрим <tex>v_1, v_2, ..., v_p</tex> — путь от корня до листа. <br />
<br />
Будем называть ветвящейся ту вершину, у которой по крайне мере два сына имеют выделенных потомков. Докажем по индукции, что если среди <tex>v_1, v_2, ..., v_i</tex> вершин есть <tex>k</tex> ветвящихся, то <tex>v_{i + 1}</tex> имеет хотя бы <tex>l^{2m + 3 - k}</tex> выделенных потомков. <br>База индукции: <tex>i = 0</tex>. Тогда <tex>k = 0</tex> и <tex>v_1</tex> имеет по крайне мере <tex>n</tex> выделенных потомков, поскольку является корнем. <br>Индукционный переход. Если <tex>v_i</tex> не является ветвящейся вершиной, то <tex>v_{i + 1}</tex> имеет такое же число ветвящихся потомков, как и <tex>v_i</tex>. Если <tex>v_i</tex> — ветвящаяся вершина, то <tex>v_{i + 1}</tex> имеет не более чем в <tex>l</tex> раз меньшее число выделенных потомков.<br />
<br />
Поскольку <tex>v_1</tex> имеет хотя бы <tex>n = l^{2m + 3}</tex> выделенных потомков, то <tex>v_1, v_2, ..., v_p</tex> содержит по крайне мере <tex>2m + 3</tex> ветвящиеся вершин. Заметим, что <tex>v_p</tex> — лист, поэтому <tex>p > 2m + 3</tex>.<br />
<br />
[[Файл:derivation_tree_T.png|240px|thumb|left|Дерево вывода <tex>T</tex>]]Будем называть <tex>v_i</tex> левой ветвящейся вершиной, если ее сын, не принадлежащий пути <tex>v_1, v_2, ..., v_p</tex>, имеет выделенного потомка, лежащего слева от <tex>v_p</tex>. В противном случае назовем <tex>v_i</tex> правой ветвящейся вершиной. Рассмотрим последние <tex>2m + 3</tex> вершины, принадлежащие пути <tex>v_1, v_2, ..., v_p</tex>. Предположим, что хотя бы <tex>m + 2</tex> вершины {{---}} левые ветвящиеся (случай, когда хотя бы <tex>m + 2</tex> вершины {{---}} правые ветвящиеся, разбирается аналогично). Пусть <tex>u_1, u_2, ..., u_{m + 2}</tex> — последние <tex>m + 2</tex> левые ветвящиеся вершины. Поскольку <tex>m = |N|</tex>, то среди них можно найти как минимум две вершины, соответствующие одному нетерминалу. Обозначим эти вершины <tex>a</tex> и <tex>b</tex>, причем <tex>b</tex> {{---}} потомок <tex>a</tex>. Тогда на рисунке показано, как представить <tex>\omega</tex> в требуемом виде.<br />
<br />
<br />
Условие (1) выполнено, поскольку <tex>x</tex> содержит выделенную вершину, а именно <tex>v_p</tex>. Очевидно, что условие (4) выполнено в силу предложенного разбиения <tex>\omega</tex>. Кроме того, <tex>u</tex> содержит выделенную вершину, а именно потомка некоторого сына вершины <tex>u_1</tex>. Аналогично, выделенный потомок некоторого сына вершины <tex>a</tex> содержится в <tex>v</tex>. Таким образом, условие (2) выполнено. Поскольку между <tex>v_p</tex> и <tex>a</tex> не более <tex>2m + 3</tex> вершин, вершина <tex>a</tex> имеет не более <tex>n</tex> выделенных потомков, поэтому условие (3) выполнено.<br />
}}<br />
<br />
== Пример не КС-языка, для которого выполняется лемма ==<br />
Докажем, что можно построить такой язык, для которого будет выполняться лемма Огдена, однако он не будет контекстно-свободным. Выберем <tex>P</tex> {{---}} подмножество <tex>N</tex> и <br />
<br />
<tex>A_{p} = \{ (ab)^n \mid P \in N \} </tex><br />
<br />
<tex>B_{p} = A_{p} \cup X^* \{aa, bb\}X^*</tex><br />
<br />
Языки над <tex>X=\{a, b\}</tex>.<br />
<br />
Очевидно, что <tex>B_{p}</tex> КС, если <tex>A_{p}</tex> контекстно-свободен. <tex>B_{p}</tex> является рекурсивно-перечислимым, если и <tex>A_{p}</tex> им является. <br />
<br />
Для <tex>B_{p}</tex> будет выполняться лемма Огдена для <tex>n = 4</tex>. Выбрав <tex>A_{p}</tex> таким образом, чтобы он был рекурсивно-перечислимым, мы создадим такой язык. (Такие языки существуют) <br />
<br />
== См. также ==<br />
[[Лемма_о_разрастании_для_КС-грамматик|Лемма о разрастании для КС-грамматик]]<br />
<br />
== Источники ==<br />
<br />
*Hopcroft, Motwani and Ullman {{---}} Automata Theory, Languages, and Computation {{---}} Addison-Wesley, 1979. ISBN 81-7808-347-7.<br />
*Ogden, W. (1968). "A helpful result for proving inherent ambiguity". Mathematical Systems Theory. 2 (3): 191–194.<br />
*[http://archive.numdam.org/ARCHIVE/ITA/ITA_1978__12_3/ITA_1978__12_3_201_0/ITA_1978__12_3_201_0.pdf On languages satisfying Ogden's lemma]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9B%D0%B5%D0%BC%D0%BC%D0%B0_%D0%9E%D0%B3%D0%B4%D0%B5%D0%BD%D0%B0&diff=58614Лемма Огдена2017-01-03T19:23:04Z<p>Zernov: </p>
<hr />
<div>{{Лемма<br />
|statement=<br />
Для каждой [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободной грамматики]] <tex>\Gamma =\langle \Sigma, N, S \in N, P \subset N\times (\Sigma\cup N)^{*}\rangle</tex> существует такое <tex>n</tex>, что для любого слова <tex>\omega \in L(\Gamma)</tex> длины не менее <tex>n</tex> и для любых выделенных в <tex>\omega</tex> не менее <tex>n</tex> позиций, <tex>\omega</tex> может быть представлено в виде <tex>\omega=uvxyz</tex>, причем:<br />
# <tex>x</tex> содержит выделенную позицию;<br />
# либо <tex>u</tex> и <tex>v</tex>, либо <tex>y</tex> и <tex>z</tex> обе содержат выделенные позиции;<br />
# <tex>vxy</tex> содержат не более <tex>n</tex> выделенных позиций;<br />
# существует <tex>A \in N</tex>, такой что <tex>S \Rightarrow^{+} uAz \Rightarrow^{+} uvAyz \Rightarrow^{+} uvxyz</tex>.<br />
|proof=<br />
Введем следующие обозначения: <tex>m = |N|</tex> и <tex>l</tex> — длина самой длинной правой части правила из <tex>P</tex>. Тогда в качестве <tex>n</tex> возьмем <tex>l^{2m + 3}</tex>. Рассмотрим дерево разбора <tex>T</tex> для произвольного слова <tex>\omega \in L(\Gamma)</tex>, у которого <tex>|\omega| \ge n</tex>. В силу выбора <tex>n</tex> в <tex>T</tex> будет по крайне мере один путь от корня до листа длины не менее <tex>2m + 3</tex>. Произвольным образом выделим в <tex>\omega</tex> не менее <tex>n</tex> позиций. Соответствующие этим позициям листья дерева <tex>T</tex> будем называть выделенными.<br />
<br />
Пусть <tex>v_1</tex> — корень <tex>T</tex>, а <tex>v_{i + 1}</tex> — сын <tex>v_i</tex>, который имеет среди своих потомков наибольшее число выделенных листьев (если таких несколько, то <tex>v_{i + 1}</tex> самый правый из них). Рассмотрим <tex>v_1, v_2, ..., v_p</tex> — путь от корня до листа. <br />
<br />
Будем называть ветвящейся ту вершину, у которой по крайне мере два сына имеют выделенных потомков. Докажем по индукции, что если среди <tex>v_1, v_2, ..., v_i</tex> вершин есть <tex>k</tex> ветвящихся, то <tex>v_{i + 1}</tex> имеет хотя бы <tex>l^{2m + 3 - k}</tex> выделенных потомков. <br>База индукции: <tex>i = 0</tex>. Тогда <tex>k = 0</tex> и <tex>v_1</tex> имеет по крайне мере <tex>n</tex> выделенных потомков, поскольку является корнем. <br>Индукционный переход. Если <tex>v_i</tex> не является ветвящейся вершиной, то <tex>v_{i + 1}</tex> имеет такое же число ветвящихся потомков, как и <tex>v_i</tex>. Если <tex>v_i</tex> — ветвящаяся вершина, то <tex>v_{i + 1}</tex> имеет не более чем в <tex>l</tex> раз меньшее число выделенных потомков.<br />
<br />
Поскольку <tex>v_1</tex> имеет хотя бы <tex>n = l^{2m + 3}</tex> выделенных потомков, то <tex>v_1, v_2, ..., v_p</tex> содержит по крайне мере <tex>2m + 3</tex> ветвящиеся вершин. Заметим, что <tex>v_p</tex> — лист, поэтому <tex>p > 2m + 3</tex>.<br />
<br />
[[Файл:derivation_tree_T.png|240px|thumb|left|Дерево вывода <tex>T</tex>]]Будем называть <tex>v_i</tex> левой ветвящейся вершиной, если ее сын, не принадлежащий пути <tex>v_1, v_2, ..., v_p</tex>, имеет выделенного потомка, лежащего слева от <tex>v_p</tex>. В противном случае назовем <tex>v_i</tex> правой ветвящейся вершиной. Рассмотрим последние <tex>2m + 3</tex> вершины, принадлежащие пути <tex>v_1, v_2, ..., v_p</tex>. Предположим, что хотя бы <tex>m + 2</tex> вершины {{---}} левые ветвящиеся (случай, когда хотя бы <tex>m + 2</tex> вершины {{---}} правые ветвящиеся, разбирается аналогично). Пусть <tex>u_1, u_2, ..., u_{m + 2}</tex> — последние <tex>m + 2</tex> левые ветвящиеся вершины. Поскольку <tex>m = |N|</tex>, то среди них можно найти как минимум две вершины, соответствующие одному нетерминалу. Обозначим эти вершины <tex>a</tex> и <tex>b</tex>, причем <tex>b</tex> {{---}} потомок <tex>a</tex>. Тогда на рисунке показано, как представить <tex>\omega</tex> в требуемом виде.<br />
<br />
<br />
Условие (1) выполнено, поскольку <tex>x</tex> содержит выделенную вершину, а именно <tex>v_p</tex>. Очевидно, что условие (4) выполнено в силу предложенного разбиения <tex>\omega</tex>. Кроме того, <tex>u</tex> содержит выделенную вершину, а именно потомка некоторого сына вершины <tex>u_1</tex>. Аналогично, выделенный потомок некоторого сына вершины <tex>a</tex> содержится в <tex>v</tex>. Таким образом, условие (2) выполнено. Поскольку между <tex>v_p</tex> и <tex>a</tex> не более <tex>2m + 3</tex> вершин, вершина <tex>a</tex> имеет не более <tex>n</tex> выделенных потомков, поэтому условие (3) выполнено.<br />
}}<br />
<br />
== См. также ==<br />
[[Лемма_о_разрастании_для_КС-грамматик|Лемма о разрастании для КС-грамматик]]<br />
<br />
== Источники ==<br />
<br />
*Hopcroft, Motwani and Ullman {{---}} Automata Theory, Languages, and Computation {{---}} Addison-Wesley, 1979. ISBN 81-7808-347-7.<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58611Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-03T18:40:55Z<p>Zernov: /* Пример */</p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]].<br />
<br />
== Пример ==<br />
=== Система уравнений ===<br />
[[Файл:at_least_one_zero.png|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел, в которых есть хотя бы один ноль<br />
<br />
<tex><br />
\begin{cases}<br />
L_1 = 1L_1\\<br />
L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon <br />
\end{cases}<br />
</tex><br />
<br />
Найдем <tex> L_1 </tex>:<br />
<br />
<tex>L_1 = 1L_1</tex>.<br />
<br />
Так как <tex> \varepsilon \notin 1 </tex>, то <tex>L_1 = 1^*</tex>.<br />
<br />
Выразим <tex> L_2 </tex> через <tex> L_1 </tex>:<br />
<br />
<tex>L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon</tex><br />
<br />
Откуда <tex>L_2 = 01^* (0 + 1)^*</tex>.<br />
<br />
=== Обычный вариант ===<br />
<br />
Теперь найдем регулярное выражение для этого же автомата с помощью теоремы Клини (обычный вариант).<br />
Для начала построим таблицу, согласно [[Теорема_Клини_(совпадение_классов_автоматных_и_регулярных_языков) | теореме]] по шагам:<br />
<br />
{| border="1" class="wikitable" style="width: 250px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Значения<br />
|-<br />
|<tex>R_{11}^{(0)}</tex><br />
|<tex>\varepsilon + 1</tex><br />
|-<br />
|<tex>R_{12}^{(0)}</tex><br />
|<tex>0</tex><br />
|-<br />
|<tex>R_{21}^{(0)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(0)}</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Например, в выражении <tex>R_{11}^{(0)}</tex> присутствует член <tex>\varepsilon</tex>, потому что и начальным, и конечным является состояние <tex>1</tex>. Это выражение включает также <tex>1</tex>, поскольку существует путь<br />
из состояния <tex>1</tex> в состояние <tex>1</tex> по входу <tex>1</tex>. Выражение <tex>R_{12}^{(0)}</tex> равно <tex>0</tex>, потому что есть дуга с<br />
меткой <tex>0</tex>, ведущая из состояния <tex>1</tex> в состояние <tex>2</tex>. Здесь нет члена <tex>\varepsilon</tex>, поскольку начальное<br />
и конечное состояния различаются. И, наконец, <tex>R_{21}^{(0)} = \varnothing</tex>, так как нет путей, ведущих из<br />
состояния <tex>2</tex> в состояние <tex>1</tex>.<br />
Теперь применим индукцию для построения более сложных выражений. <br />
<br />
Правило для вычисления выражения <tex>R_{ij}^{(1)}</tex> представляет собой пример общего правила из части теоремы Клини:<br />
<br />
<tex>R_{ij}^{(1)} = R_{ij}^{(0)} + R_{i1}^{(0)} (R_{11}^{(0)})^* R_{1j}^{(0)}</tex><br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Прямая подстановка<br />
!style="background:#41aef0"|Упрощенное выражение<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>\varepsilon + 1 + (\varepsilon + 1)(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>0 + (\varepsilon + 1)(\varepsilon + 1)^*0</tex><br />
|<tex>1^*0</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing + \varnothing(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>\varepsilon + 0 + 1 + \varnothing(\varepsilon + 1)^*0</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
И, наконец, последний шаг индукции<br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Упрощенное выражение (после подстановки)<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>1^*0(0 + 1)^*</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>(0 + 1)^*</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Окончательное регулярное выражение, эквивалентное автомату, строится путем объединения всех тех выражений, для которых первое состояние<br />
является начальным, а второе {{---}} заключительным. В нашем примере <tex>1</tex> {{---}} начальное состояние, а <tex>2</tex> {{---}} заключительное, поэтому нам нужно лишь выражение <tex>R_{12}^{(1)}</tex>, равное <tex>1^*0(0 + 1)^*</tex><br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini Mathhelpplanet {{---}} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. {{---}} М.: Издательский дом «Вильямс», 2008. {{---}} С. 112 {{---}} ISBN 978-5-8459-1347-0 <br />
<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58610Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-03T18:39:51Z<p>Zernov: /* Пример */</p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]].<br />
<br />
== Пример ==<br />
[[Файл:at_least_one_zero.png|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел, в которых есть хотя бы один ноль<br />
<br />
<tex><br />
\begin{cases}<br />
L_1 = 1L_1\\<br />
L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon <br />
\end{cases}<br />
</tex><br />
<br />
Найдем <tex> L_1 </tex>:<br />
<br />
<tex>L_1 = 1L_1</tex>.<br />
<br />
Так как <tex> \varepsilon \notin 1 </tex>, то <tex>L_1 = 1^*</tex>.<br />
<br />
Выразим <tex> L_2 </tex> через <tex> L_1 </tex>:<br />
<br />
<tex>L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon</tex><br />
<br />
Откуда <tex>L_2 = 01^* (0 + 1)^*</tex>.<br />
<br />
Теперь найдем регулярное выражение для этого же автомата с помощью теоремы Клини (обычный вариант).<br />
Для начала построим таблицу, согласно [[Теорема_Клини_(совпадение_классов_автоматных_и_регулярных_языков) | теореме]] по шагам:<br />
<br />
{| border="1" class="wikitable" style="width: 250px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Значения<br />
|-<br />
|<tex>R_{11}^{(0)}</tex><br />
|<tex>\varepsilon + 1</tex><br />
|-<br />
|<tex>R_{12}^{(0)}</tex><br />
|<tex>0</tex><br />
|-<br />
|<tex>R_{21}^{(0)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(0)}</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Например, в выражении <tex>R_{11}^{(0)}</tex> присутствует член <tex>\varepsilon</tex>, потому что и начальным, и конечным является состояние <tex>1</tex>. Это выражение включает также <tex>1</tex>, поскольку существует путь<br />
из состояния <tex>1</tex> в состояние <tex>1</tex> по входу <tex>1</tex>. Выражение <tex>R_{12}^{(0)}</tex> равно <tex>0</tex>, потому что есть дуга с<br />
меткой <tex>0</tex>, ведущая из состояния <tex>1</tex> в состояние <tex>2</tex>. Здесь нет члена <tex>\varepsilon</tex>, поскольку начальное<br />
и конечное состояния различаются. И, наконец, <tex>R_{21}^{(0)} = \varnothing</tex>, так как нет путей, ведущих из<br />
состояния <tex>2</tex> в состояние <tex>1</tex>.<br />
Теперь применим индукцию для построения более сложных выражений. <br />
<br />
Правило для вычисления выражения <tex>R_{ij}^{(1)}</tex> представляет собой пример общего правила из части теоремы Клини:<br />
<br />
<tex>R_{ij}^{(1)} = R_{ij}^{(0)} + R_{i1}^{(0)} (R_{11}^{(0)})^* R_{1j}^{(0)}</tex><br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Прямая подстановка<br />
!style="background:#41aef0"|Упрощенное выражение<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>\varepsilon + 1 + (\varepsilon + 1)(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>0 + (\varepsilon + 1)(\varepsilon + 1)^*0</tex><br />
|<tex>1^*0</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing + \varnothing(\varepsilon + 1)^*(\varepsilon + 1)</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>\varepsilon + 0 + 1 + \varnothing(\varepsilon + 1)^*0</tex><br />
|<tex>(\varepsilon + 0 + 1)</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
И, наконец, последний шаг индукции<br />
<br />
{| border="1" class="wikitable" style="width: 300px; height: 250px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Упрощенное выражение (после подстановки)<br />
|-<br />
|<tex>R_{11}^{(1)}</tex><br />
|<tex>1^*</tex><br />
|-<br />
|<tex>R_{12}^{(1)}</tex><br />
|<tex>1^*0(0 + 1)^*</tex><br />
|-<br />
|<tex>R_{21}^{(1)}</tex><br />
|<tex>\varnothing</tex><br />
|-<br />
|<tex>R_{22}^{(1)}</tex><br />
|<tex>(0 + 1)^*</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
Окончательное регулярное выражение, эквивалентное автомату, строится путем объединения всех тех выражений, для которых первое состояние<br />
является начальным, а второе {{---}} заключительным. В нашем примере <tex>1</tex> {{---}} начальное состояние, а <tex>2</tex> {{---}} заключительное, поэтому нам нужно лишь выражение <tex>R_{12}^{(1)}</tex>, равное <tex>1^*0(0 + 1)^*</tex><br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini Mathhelpplanet {{---}} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. {{---}} М.: Издательский дом «Вильямс», 2008. {{---}} С. 112 {{---}} ISBN 978-5-8459-1347-0 <br />
<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58609Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-03T18:16:30Z<p>Zernov: /* Источники информации */</p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]].<br />
<br />
== Пример ==<br />
[[Файл:at_least_one_zero.png|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел, в которых есть хотя бы один ноль<br />
<br />
<tex><br />
\begin{cases}<br />
L_1 = 1L_1\\<br />
L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon <br />
\end{cases}<br />
</tex><br />
<br />
Найдем <tex> L_1 </tex>:<br />
<br />
<tex>L_1 = 1L_1</tex>.<br />
<br />
Так как <tex> \varepsilon \notin 1 </tex>, то <tex>L_1 = 1^*</tex>.<br />
<br />
Выразим <tex> L_2 </tex> через <tex> L_1 </tex>:<br />
<br />
<tex>L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon</tex><br />
<br />
Откуда <tex>L_2 = 01^* (0 + 1)^*</tex>.<br />
<br />
Теперь найдем регулярное выражение для этого же автомата с помощью теоремы Клини (обычный вариант).<br />
Для начала построим таблицу, согласно [[Теорема_Клини_(совпадение_классов_автоматных_и_регулярных_языков) | теореме]] по шагам:<br />
<br />
{| border="1" class="wikitable" style="width: 500px; height: 100px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Значения<br />
|-<br />
|<br />
|<br />
<br />
|}<br />
<div style="clear:both;"></div><br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini Mathhelpplanet {{---}} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. {{---}} М.: Издательский дом «Вильямс», 2008. {{---}} С. 112 {{---}} ISBN 978-5-8459-1347-0 <br />
<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58608Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-03T18:14:22Z<p>Zernov: /* Пример */</p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]].<br />
<br />
== Пример ==<br />
[[Файл:at_least_one_zero.png|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел, в которых есть хотя бы один ноль<br />
<br />
<tex><br />
\begin{cases}<br />
L_1 = 1L_1\\<br />
L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon <br />
\end{cases}<br />
</tex><br />
<br />
Найдем <tex> L_1 </tex>:<br />
<br />
<tex>L_1 = 1L_1</tex>.<br />
<br />
Так как <tex> \varepsilon \notin 1 </tex>, то <tex>L_1 = 1^*</tex>.<br />
<br />
Выразим <tex> L_2 </tex> через <tex> L_1 </tex>:<br />
<br />
<tex>L_2 = 0L_1 + 0L_2 + 1L_2 + \varepsilon</tex><br />
<br />
Откуда <tex>L_2 = 01^* (0 + 1)^*</tex>.<br />
<br />
Теперь найдем регулярное выражение для этого же автомата с помощью теоремы Клини (обычный вариант).<br />
Для начала построим таблицу, согласно [[Теорема_Клини_(совпадение_классов_автоматных_и_регулярных_языков) | теореме]] по шагам:<br />
<br />
{| border="1" class="wikitable" style="width: 500px; height: 100px; float: left;"<br />
!style="background:#41aef0"|Выражение<br />
!style="background:#41aef0"|Значения<br />
|-<br />
|<br />
|<br />
<br />
|}<br />
<div style="clear:both;"></div><br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini Mathhelpplanet {{---}} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:At_least_one_zero.png&diff=58602Файл:At least one zero.png2017-01-03T17:32:31Z<p>Zernov: </p>
<hr />
<div></div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58600Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-03T17:05:31Z<p>Zernov: /* Источники информации */</p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]].<br />
<br />
== Пример ==<br />
[[file:Автомат2.png|450px|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел кратных трем.<br />
<br />
<tex><br />
\begin{cases}<br />
L_0 = 0L_0+1L_1+\varepsilon \\<br />
L_1 = 1L_0+0L_2 \\<br />
L_2 = 0L_1+1L_2<br />
\end{cases}<br />
</tex><br />
<br />
Выразим <tex>L_2</tex> из третьего уравнения, подставив <tex> L_1 </tex> из второго:<br />
<br />
<tex>L_2 = (00 + 1)L_2+01L_0</tex>.<br />
<br />
Так как <tex> \varepsilon \notin (00 + 1) </tex>, то <tex>L_2 = (00+1)^*01L_0</tex>.<br />
<br />
Подставим <tex>L_2</tex> во второе уравнение, а потом получившееся выражение подставим в первое, чтобы найти <tex>L_0</tex>:<br />
<br />
<tex>L_0 = 0L_0 + 11L_0 + 10(00+1)^*01L_0 + \varepsilon </tex>.<br />
<br />
Решив уравнение, получим что <tex>(0 + 11 + 10(00+1)^*01)^*</tex> {{---}} регулярное выражение, порождающее искомый язык.<br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini Mathhelpplanet {{---}} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58599Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-03T17:04:49Z<p>Zernov: /* Источники информации */</p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]].<br />
<br />
== Пример ==<br />
[[file:Автомат2.png|450px|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел кратных трем.<br />
<br />
<tex><br />
\begin{cases}<br />
L_0 = 0L_0+1L_1+\varepsilon \\<br />
L_1 = 1L_0+0L_2 \\<br />
L_2 = 0L_1+1L_2<br />
\end{cases}<br />
</tex><br />
<br />
Выразим <tex>L_2</tex> из третьего уравнения, подставив <tex> L_1 </tex> из второго:<br />
<br />
<tex>L_2 = (00 + 1)L_2+01L_0</tex>.<br />
<br />
Так как <tex> \varepsilon \notin (00 + 1) </tex>, то <tex>L_2 = (00+1)^*01L_0</tex>.<br />
<br />
Подставим <tex>L_2</tex> во второе уравнение, а потом получившееся выражение подставим в первое, чтобы найти <tex>L_0</tex>:<br />
<br />
<tex>L_0 = 0L_0 + 11L_0 + 10(00+1)^*01L_0 + \varepsilon </tex>.<br />
<br />
Решив уравнение, получим что <tex>(0 + 11 + 10(00+1)^*01)^*</tex> {{---}} регулярное выражение, порождающее искомый язык.<br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [http://mathhelpplanet.com/static.php?p=teorema-klini mathhelpplanet {{---} Теорема Клини]<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Deepak D’Souza {{---}} Regular Expressions]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D1%8C%D1%82%D0%B5%D1%80%D0%BD%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D0%B5%D0%BE%D1%80%D0%B5%D0%BC%D1%8B_%D0%9A%D0%BB%D0%B8%D0%BD%D0%B8_(%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%83_%D1%83%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%B2_%D1%80%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D1%85_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85)&diff=58598Альтернативное доказательство теоремы Клини (через систему уравнений в регулярных выражениях)2017-01-03T16:55:44Z<p>Zernov: </p>
<hr />
<div>== Альтернативное доказательство ==<br />
<br />
{{Теорема<br />
|statement=Класс [[Детерминированные_конечные_автоматы#Автоматные_языки | автоматных]] языков является подмножеством [[Регулярные языки:_два определения_и_их_эквивалентность#REG1 | регулярных]].<br />
|proof=<br />
<br />
[[file:Автомат1.png|200px|right]]<br />
Рассмотрим автоматный язык <tex>L</tex> и ДКА для него. Для доказательства теоремы достаточно построить регулярное выражение, порождающее язык <tex>L</tex>.<br />
<br />
Пусть наш автомат состоит из <tex>n</tex> состояний, и состояние <tex>0</tex> — стартовое. Также пусть <tex>L_i</tex> — язык, состоящий из слов, которые приводят из состояния <tex>i</tex> в терминальное.<br />
<br />
Заметим, что <tex>L_i = \bigcup c L_j</tex> для всех <tex> c \in \Sigma </tex> и <tex>j</tex> таких, что <tex>\delta(i, c)=j</tex>. Действительно, если по слову <tex> \alpha </tex> из состояния <tex>j</tex> мы можем попасть в терминальное состояние, а между состояниями <tex> i </tex> и <tex> j </tex> есть переход по символу <tex> c </tex>, то слово <tex> c \alpha </tex> принадлежит языку <tex>L_i</tex>. Также, если <tex>\varepsilon \in L_i</tex>, то есть если состояние является терминальным, то добавим <tex>\varepsilon</tex> в объединение для <tex>L_i</tex>.<br />
<br />
Мы получили [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | систему]] из <tex>n</tex> регулярных выражений с <tex>n</tex> неизвестными, причем <tex> \varepsilon \notin \alpha_{ij}</tex> (<tex> \alpha_{ij} </tex> {{---}} коэффициент перед <tex> j </tex>-й переменной в <tex> i </tex>-м [[Решение уравнений в регулярных выражениях#Решение системы уравнений в регулярных выражениях | уравнении]]) для всех <tex> i </tex> и <tex> j </tex>, так как в автомате нет <tex> \varepsilon </tex>-переходов, а следовательно, система имеет единственное решение. Также заметим, что <tex>L_0</tex> содержит все слова, по которым из стартового состояния можно дойти до терминального, но тогда <tex>L_0 = L</tex>.<br />
<br />
В итоге мы построили систему уравнений в регулярных выражениях, решив которую, мы получим регулярное выражение, порождающее язык <tex>L</tex>.<br />
}}<br />
<br />
Отметим, что длина построенного таким образом регулярного выражения обычно заметно короче, чем если бы мы строили его по [[Теорема Клини (совпадение классов автоматных и регулярных языков) | теореме Клини]].<br />
<br />
== Пример ==<br />
[[file:Автомат2.png|450px|right]]<br />
Найдем регулярное выражение для языка двоичных представлений чисел кратных трем.<br />
<br />
<tex><br />
\begin{cases}<br />
L_0 = 0L_0+1L_1+\varepsilon \\<br />
L_1 = 1L_0+0L_2 \\<br />
L_2 = 0L_1+1L_2<br />
\end{cases}<br />
</tex><br />
<br />
Выразим <tex>L_2</tex> из третьего уравнения, подставив <tex> L_1 </tex> из второго:<br />
<br />
<tex>L_2 = (00 + 1)L_2+01L_0</tex>.<br />
<br />
Так как <tex> \varepsilon \notin (00 + 1) </tex>, то <tex>L_2 = (00+1)^*01L_0</tex>.<br />
<br />
Подставим <tex>L_2</tex> во второе уравнение, а потом получившееся выражение подставим в первое, чтобы найти <tex>L_0</tex>:<br />
<br />
<tex>L_0 = 0L_0 + 11L_0 + 10(00+1)^*01L_0 + \varepsilon </tex>.<br />
<br />
Решив уравнение, получим что <tex>(0 + 11 + 10(00+1)^*01)^*</tex> {{---}} регулярное выражение, порождающее искомый язык.<br />
<br />
== См. также ==<br />
* [[Теорема Клини (совпадение классов автоматных и регулярных языков) | Теорема Клини]]<br />
* [[Решение уравнений в регулярных выражениях | Решение уравнений в регулярных выражениях ]]<br />
<br />
== Источники информации==<br />
* [https://drona.csa.iisc.ernet.in/~deepakd/atc-2011/regular-exp.pdf Regular Expressions {{---}} Deepak D’Souza]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Автоматы и регулярные языки]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57092Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T22:14:29Z<p>Zernov: </p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
:<tex> A \rightarrow a\gamma </tex><br />
<br />
:<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал (возможно, стартовый), <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов.<br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
:<tex> A \rightarrow a\gamma </tex><br />
<br />
:<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал (возможно, стартовый), <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей функцией для придания грамматике нужного вида:<br />
greibah(правила <tex>A_1 \dots A_n</tex> из контекстно-свободной грамматики <tex> \Gamma </tex>) <br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j </tex> вида <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \geqslant i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем функцию '''greibah''' для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем функцию '''greibah''' для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>. <ref>[http://www.cis.upenn.edu/~jean/old511/html/cis51108sl4b.pdf Jean Gallier {{---}} Discrete Mathematics]</ref><br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
== См. также ==<br />
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]<br />
* [[Нормальная_форма_Куроды | Нормальная форма Куроды]]<br />
* [[Нормальная_форма_Хомского | Нормальная форма Хомского]]<br />
<br />
==Примечания==<br />
<br />
<references /><br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: Нормальные формы КС-грамматик]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57091Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T22:13:02Z<p>Zernov: /* Приведение грамматики к ослабленной нормальной форме Грейбах */</p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
:<tex> A \rightarrow a\gamma </tex><br />
<br />
:<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. Таким образом, пустая строка выводится только из стартового нетерминала, однако он по-прежнему может участвовать в формировании правил первого типа. (Это утверждение применимо и к ослабленной нормальной форме Грейбах) <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
:<tex> A \rightarrow a\gamma </tex><br />
<br />
:<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей функцией для придания грамматике нужного вида:<br />
greibah(правила <tex>A_1 \dots A_n</tex> из контекстно-свободной грамматики <tex> \Gamma </tex>) <br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j </tex> вида <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \geqslant i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем функцию '''greibah''' для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем функцию '''greibah''' для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>. <ref>[http://www.cis.upenn.edu/~jean/old511/html/cis51108sl4b.pdf Jean Gallier {{---}} Discrete Mathematics]</ref><br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
== См. также ==<br />
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]<br />
* [[Нормальная_форма_Куроды | Нормальная форма Куроды]]<br />
* [[Нормальная_форма_Хомского | Нормальная форма Хомского]]<br />
<br />
==Примечания==<br />
<br />
<references /><br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: Нормальные формы КС-грамматик]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57090Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T22:05:46Z<p>Zernov: </p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
:<tex> A \rightarrow a\gamma </tex><br />
<br />
:<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. Таким образом, пустая строка выводится только из стартового нетерминала, однако он по-прежнему может участвовать в формировании правил первого типа. (Это утверждение применимо и к ослабленной нормальной форме Грейбах) <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
:<tex> A \rightarrow a\gamma </tex><br />
<br />
:<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей функцией для придания грамматике нужного вида:<br />
'''greibah'''(<tex> \Gamma </tex>) <br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \geqslant i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем функцию '''greibah''' для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем функцию '''greibah''' для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>. <ref>[http://www.cis.upenn.edu/~jean/old511/html/cis51108sl4b.pdf Jean Gallier {{---}} Discrete Mathematics]</ref><br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
== См. также ==<br />
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]<br />
* [[Нормальная_форма_Куроды | Нормальная форма Куроды]]<br />
* [[Нормальная_форма_Хомского | Нормальная форма Хомского]]<br />
<br />
==Примечания==<br />
<br />
<references /><br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: Нормальные формы КС-грамматик]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D1%82%D0%B5%D1%80%D0%BC%D0%B8%D0%BD%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5_%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D1%8B_%D1%81_%D0%BC%D0%B0%D0%B3%D0%B0%D0%B7%D0%B8%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D1%8C%D1%8E,_%D0%B4%D0%BE%D0%BF%D1%83%D1%81%D0%BA_%D0%BF%D0%BE_%D0%BF%D1%83%D1%81%D1%82%D0%BE%D0%BC%D1%83_%D1%81%D1%82%D0%B5%D0%BA%D1%83&diff=57088Детерминированные автоматы с магазинной памятью, допуск по пустому стеку2016-12-06T21:28:57Z<p>Zernov: </p>
<hr />
<div>{{Определение<br />
|definition =<br />
Определим '''детерминированный автомат с магазинной памятью, допускающий по пустому стеку''' (англ. ''PDA accepting by empty stack''), как [[Детерминированные_автоматы_с_магазинной_памятью|детерминированный автомат с магазинной памятью]], у которого нет множества <tex>T</tex> допускающих состояний. Автомат заканчивает свою работу как только стек становится пустым.<br />
}}<br />
Определим для него множество допускающих слов <tex>N = \{\omega \mid (q_0,a_0,Z_0)\vdash^* (p,\epsilon,\epsilon)\}</tex>, где <tex>p</tex> {{---}} произвольное состояние.<br />
{{Определение<br />
|definition =<br />
Язык называется '''беспрефиксным''' (англ. ''prefix-free''), если для любой пары слов из этого языка ни одно из этих слов не является префиксом другого.<br />
}}<br />
{{Теорема<br />
|statement=Язык <tex>L</tex> допускается ДМП-автоматом, допускающему по пустому стеку тогда и только тогда, когда язык <tex>L</tex> допускается ДМП-автоматом, допускающему по допускающему состоянию и <tex>L</tex> {{---}} беспрефиксный.<br />
|proof=<br />
<tex>\Rightarrow</tex><br><br />
<br />
:Допустим, что <tex>L</tex> не беспрефиксный. Тогда <tex>\exists \omega_1, \omega_2 \in L : \omega_2 = \omega_1 \alpha</tex>. Попробуем допустить слово <tex>\omega_2</tex>. Тогда автомат остановится сразу после префикса <tex>\omega_1</tex>, т.к. <tex>\omega_1 \in L</tex>. Стек будет пустой, однако до конца слова <tex>\omega_2</tex> мы не дойдем, поэтому оно не допустится, хотя содержится в <tex>L</tex>. Получили противоречие, значит <tex>L</tex> {{---}} беспрефиксный.<br />
<br />
Построим по заданному ДМП-автомату с допуском по пустому стеку ДМП с допуском по допускающему состоянию.<br> <br><br />
[[Файл:ДМП1.png]]<br><br />
<tex>\Leftarrow</tex><br><br />
:Пусть задан ДМП-автомат с допуском по допускающему состоянию, язык <tex>L</tex> {{---}} беспрефиксный. Если автомат в какой-то момент пришел в допускающее состояние, то дальше идти смысла нет, т.к. тогда бы слово, допускаемое этим состоянием было бы префиксом некоторого другого слова. Значит можем удалить все переходы из допускающих состояний и добавить переходы в очистку стека.<br><br />
[[Файл:ДМП2.png]]<br />
}}<br />
<br />
==Источники информации==<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' {{---}} '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2008. : ISBN 978-5-8459-1347-0 (рус.)<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: МП-автоматы]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D1%82%D0%B5%D1%80%D0%BC%D0%B8%D0%BD%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5_%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D1%8B_%D1%81_%D0%BC%D0%B0%D0%B3%D0%B0%D0%B7%D0%B8%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D1%8C%D1%8E,_%D0%B4%D0%BE%D0%BF%D1%83%D1%81%D0%BA_%D0%BF%D0%BE_%D0%BF%D1%83%D1%81%D1%82%D0%BE%D0%BC%D1%83_%D1%81%D1%82%D0%B5%D0%BA%D1%83&diff=57087Детерминированные автоматы с магазинной памятью, допуск по пустому стеку2016-12-06T21:21:14Z<p>Zernov: </p>
<hr />
<div>{{Определение<br />
|definition =<br />
Определим <b>детерминированный автомат с магазинной памятью, допускающий по пустому стеку</b>, как [[Детерминированные_автоматы_с_магазинной_памятью|детерминированный автомат с магазинной памятью]], у которого нет множества <tex>T</tex> допускающих состояний. Автомат заканчивает свою работу как только стек становится пустым.<br />
}}<br />
Определим для него множество допускающих слов <tex>N = \{\omega \mid (q_0,a_0,Z_0)\vdash^* (p,\epsilon,\epsilon)\}</tex>, где <tex>p</tex> {{---}} произвольное состояние.<br />
{{Определение<br />
|definition =<br />
Язык называется <b>беспрефиксным</b>, если для любой пары слов из этого языка ни одно из этих слов не является префиксом другого.<br />
}}<br />
{{Теорема<br />
|statement=Язык <tex>L</tex> допускается ДМП-автоматом, допускающему по пустому стеку тогда и только тогда, когда язык <tex>L</tex> допускается ДМП-автоматом, допускающему по допускающему состоянию и <tex>L</tex> {{---}} беспрефиксный.<br />
|proof=<br />
<tex>\Rightarrow</tex><br><br />
<br />
:Допустим, что <tex>L</tex> не беспрефиксный. Тогда <tex>\exists \omega_1, \omega_2 \in L : \omega_2 = \omega_1 \alpha</tex>. Попробуем допустить слово <tex>\omega_2</tex>. Тогда автомат остановится сразу после префикса <tex>\omega_1</tex>, т.к. <tex>\omega_1 \in L</tex>. Стек будет пустой, однако до конца слова <tex>\omega_2</tex> мы не дойдем, поэтому оно не допустится, хотя содержится в <tex>L</tex>. Получили противоречие, значит <tex>L</tex> {{---}} беспрефиксный.<br />
<br />
Построим по заданному ДМП-автомату с допуском по пустому стеку ДМП с допуском по допускающему состоянию.<br> <br><br />
[[Файл:ДМП1.png]]<br><br />
<tex>\Leftarrow</tex><br><br />
:Пусть задан ДМП-автомат с допуском по допускающему состоянию, язык <tex>L</tex> {{---}} беспрефиксный. Если автомат в какой-то момент пришел в допускающее состояние, то дальше идти смысла нет, т.к. тогда бы слово, допускаемое этим состоянием было бы префиксом некоторого другого слова. Значит можем удалить все переходы из допускающих состояний и добавить переходы в очистку стека.<br><br />
[[Файл:ДМП2.png]]<br />
}}<br />
<br />
==Источники информации==<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' {{---}} '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2008. : ISBN 978-5-8459-1347-0 (рус.)<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: МП-автоматы]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D1%82%D0%B5%D1%80%D0%BC%D0%B8%D0%BD%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5_%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D1%8B_%D1%81_%D0%BC%D0%B0%D0%B3%D0%B0%D0%B7%D0%B8%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D1%8C%D1%8E&diff=57086Детерминированные автоматы с магазинной памятью2016-12-06T21:18:53Z<p>Zernov: </p>
<hr />
<div>{{Определение<br />
|definition =<br />
'''Детерминированным автоматом с магазинной памятью''' (англ. ''deterministic pushdown automaton'') называется [[Автоматы с магазинной памятью|автомат с магазинной памятью]], для которого выполнены следующие условия:<br />
#<tex>\mathcal8 q \in Q, a \in \Sigma \cup \{ \varepsilon \}, X \in \Gamma \Rightarrow \delta(q, a, X)</tex> имеет не более одного элемента {{---}} <tex> \delta : Q \times \Sigma \cup \{\varepsilon\} \times \Gamma \rightarrow Q \times \Gamma^*</tex>.<br />
#Если <tex>\delta (q,a,X)</tex> непусто для некоторого <tex>a \in \Sigma</tex>, то <tex>\delta (q,\varepsilon,X)</tex> должно быть пустым.<br />
}}<br />
<br />
==Пример==<br />
Построим для языка:<br />
# <tex> S \rightarrow 1H </tex><br />
# <tex> H \rightarrow 0F </tex><br />
# <tex> H \rightarrow \varepsilon </tex><br />
# <tex> F \rightarrow 0F </tex><br />
# <tex> F \rightarrow 1F </tex><br />
# <tex> F \rightarrow \varepsilon </tex><br />
автомат <tex>A=(\{0,1\}, \{Z_0,X\}, \{q,p\}, q, \{p\}, Z_0, \delta)</tex> с функией перехода <tex>\delta</tex>:<br />
# <tex>\delta(q,0,Z_0)=(q,XZ_0)</tex><br />
# <tex>\delta(q,0,X) =(q,XX)</tex><br />
# <tex>\delta(q,1,X) =(q,X)</tex><br />
# <tex>\delta(q,1,Z_0)=(p,Z_0)</tex><br />
# <tex>\delta(p,0,Z_0)=(p,XZ_0)</tex><br />
# <tex>\delta(p,0,X) =(p,XX)</tex><br />
# <tex>\delta(p,1,X) =(p,X)</tex> <br> <br><br />
[[Файл:Пример_мп-автомата.png]]<br />
<br />
== См. также ==<br />
* [[Детерминированные автоматы с магазинной памятью, допуск по пустому стеку]]<br />
* [[Несовпадение класса языков, распознаваемых ДМП автоматами и произвольными МП автоматами]]<br />
* [[ДМП-автоматы и неоднозначность]]<br />
<br />
== Источники информации ==<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' {{---}} '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2008. — 528с. : ISBN 978-5-8459-1347-0 (рус.)<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: МП-автоматы]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D1%8B_%D1%81_%D0%BC%D0%B0%D0%B3%D0%B0%D0%B7%D0%B8%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D1%8C%D1%8E&diff=57085Автоматы с магазинной памятью2016-12-06T21:18:06Z<p>Zernov: </p>
<hr />
<div>==Недетерминированный автомат с магазинной памятью==<br />
{{Определение<br />
|definition= '''Автомат с магазинной памятью''' (автомат со стеком, англ. ''pushdown automaton'') {{---}} это набор <tex>A=\langle\Sigma,\Gamma,Q,s\in Q, T \subset Q, z_0 \in \Gamma, \delta : Q \times \Sigma \cup \{\varepsilon\} \times \Gamma \rightarrow 2^Q \times \Gamma^*\rangle</tex>, где<br />
*<tex>\Sigma</tex> {{---}} входной алфавит на ленте,<br />
*<tex>\Gamma</tex> {{---}} стековый алфавит,<br />
*<tex>Q</tex> {{---}} множество состояний автомата,<br />
*<tex>s</tex> {{---}} стартовое состояние автомата,<br />
*<tex>T</tex> {{---}} множество допускающих состояний автомата,<br />
*<tex>z_0</tex> {{---}} маркер дна стека,<br />
*<tex>\delta</tex> {{---}} функция переходов.<br />
}}<br />
<br />
[[Изображение:PDAsmall.jpg|left|Рис. 1. Автомат с магазинной памятью]]<br />
С ленты последовательно считываются символы входного алфавита (<tex>c_i</tex> {{---}} текущий считываемый символ). Символ <tex>x</tex> снимается с вершины стека. Вместо него помещается строка <tex>\alpha</tex> таким образом, чтобы первый символ строки находился на вершине стека. <br />
<br />
Обычно под автоматом со стеком подразумевается недетерминированный автомат. Заметим, что [[Совпадение множества языков МП-автоматов и контекстно-свободных языков|недетерминированные автоматы со стеком эквивалентны по выразительной мощности контекстно свободным грамматикам.]] Если речь пойдет о [[Детерминированные автоматы с магазинной памятью|детерминированном автомате]], это будет указано отдельно. Заметим также, что [[Несовпадение класса языков, распознаваемых ДМП автоматами и произвольными МП автоматами|детерминированные и недетерминированные автоматы со стеком неэквивалентны]].<br />
<br style="clear:both" /><br />
<br />
==Диаграммы переходов==<br />
<div class="tleft" style="clear:none">[[Файл:Transition1.png|400px|thumb|Рис. 2. Переход: с {{---}} символ, прочитанный с ленты; A {{---}} символ, вынутый из стека; <tex>\alpha</tex> {{---}} строка, помещаемая в стек.]]</div><br />
<div class="tleft" style="clear:none">[[Файл:Transition2.png|400px|thumb|Рис. 3. Переход по любому стековому символу, он же возвращается в стек.]]</div><br />
<div class="tleft" style="clear:none">[[Файл:Transition3.png|400px|thumb|Рис. 4. Переход по любому стековому символу, в стек кладется пустая строка.]]</div><br />
<br style="clear:both" /><br />
По соглашению маркер дна всегда находится на дне (за исключением случая, когда автомат является [[МП-автоматы, допуск по пустому стеку и по допускающему состоянию, эквивалентность|автоматом с допуском по пустому стеку]]). То есть, для <tex>\mathcal8 q \in Q,\mathcal8 c \in \Sigma \cup \{\varepsilon\} \Rightarrow \delta(q, c, z_0) \ni \langle p, \alpha \rangle </tex>, где <tex>p \in Q, \alpha \in \Gamma^*, \alpha = \alpha_1z_0</tex>.<br />
<br />
==Основные определения==<br />
{{Определение<br />
|definition=<br />
'''Мгновенное описание''' (англ. ''instantaneous descriptions'') {{---}} это набор <tex>\langle q, \alpha, \gamma \rangle</tex>, где <tex>q</tex> {{---}} текущее состояние, <tex>\alpha</tex> {{---}} остаток строки, <tex>\gamma</tex> {{---}} содержимое стека.<br />
}}<br />
{{Определение<br />
|definition=<br />
'''Переход за один шаг''' (англ. ''the "goes-to" relation'') обозначается как <tex>\langle q, \alpha, \gamma \rangle \vdash \langle r, \beta, \xi \rangle</tex>, где <tex>\alpha = c\beta</tex> (возможно, <tex>c=\varepsilon</tex>), <tex>\gamma = \chi\gamma', \xi = \eta\gamma'</tex>, <tex>\langle r, \eta \rangle \in \delta(q, c, \chi)</tex>.<br />
}}<br />
{{Определение<br />
|definition= '''Язык автомата с магазинной памятью''' (англ. ''language of a pushdown automaton'') <tex>L(A)=\{\alpha \mid \langle s, \alpha, z_0\rangle \vdash^* \langle t, \varepsilon, \gamma \rangle, t \in T\}</tex>.<br />
}}<br />
<br />
==Пример недетерминированного МП-автомата==<br />
[[Изображение:PDAexample.png|300px|thumb|left|Рис. 5. Недетерминированный МП-автомат для языка <tex>0^n1^n</tex>.]]<br style="clear:both" /><br />
<br />
== См. также ==<br />
* [[Детерминированные автоматы с магазинной памятью, допуск по пустому стеку]]<br />
* [[ДМП-автоматы и неоднозначность]]<br />
<br />
== Источники информации ==<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' {{---}} '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2008. — 528 с. : ISBN 978-5-8459-1347-0 (рус.)<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: МП-автоматы]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57084Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T21:10:20Z<p>Zernov: /* Применение */</p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. Таким образом, пустая строка выводится только из стартового нетерминала, однако он по-прежнему может участвовать в формировании правил первого типа. (Это утверждение применимо и к ослабленной нормальной форме Грейбах) <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей функцией для придания грамматике нужного вида:<br />
'''greibah'''(<tex> \Gamma </tex>) <br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \geqslant i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем функцию '''greibah''' для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем функцию '''greibah''' для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>. <ref>[http://www.cis.upenn.edu/~jean/old511/html/cis51108sl4b.pdf Jean Gallier {{---}} Discrete Mathematics]</ref><br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
== См. также ==<br />
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]<br />
* [[Нормальная_форма_Куроды | Нормальная форма Куроды]]<br />
* [[Нормальная_форма_Хомского | Нормальная форма Хомского]]<br />
<br />
==Примечания==<br />
<br />
<references /><br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: Нормальные формы КС-грамматик]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57083Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T21:09:52Z<p>Zernov: </p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. Таким образом, пустая строка выводится только из стартового нетерминала, однако он по-прежнему может участвовать в формировании правил первого типа. (Это утверждение применимо и к ослабленной нормальной форме Грейбах) <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей функцией для придания грамматике нужного вида:<br />
'''greibah'''(<tex> \Gamma </tex>) <br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \geqslant i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем функцию '''greibah''' для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем функцию '''greibah''' для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>. <ref>[http://www.cis.upenn.edu/~jean/old511/html/cis51108sl4b.pdf Jean Gallier {{---}} Discrete Mathematics</ref><br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
== См. также ==<br />
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]<br />
* [[Нормальная_форма_Куроды | Нормальная форма Куроды]]<br />
* [[Нормальная_форма_Хомского | Нормальная форма Хомского]]<br />
<br />
==Примечания==<br />
<br />
<references /><br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: Нормальные формы КС-грамматик]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57082Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T21:09:05Z<p>Zernov: /* Применение */</p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. Таким образом, пустая строка выводится только из стартового нетерминала, однако он по-прежнему может участвовать в формировании правил первого типа. (Это утверждение применимо и к ослабленной нормальной форме Грейбах) <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей функцией для придания грамматике нужного вида:<br />
'''greibah'''(<tex> \Gamma </tex>) <br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \geqslant i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем функцию '''greibah''' для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем функцию '''greibah''' для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>. <ref>[http://www.cis.upenn.edu/~jean/old511/html/cis51108sl4b.pdf Jean Gallier {{---}} Discrete Mathematics</ref><br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
== См. также ==<br />
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]<br />
* [[Нормальная_форма_Куроды | Нормальная форма Куроды]]<br />
* [[Нормальная_форма_Хомского | Нормальная форма Хомского]]<br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: Нормальные формы КС-грамматик]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57081Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T21:04:37Z<p>Zernov: </p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. Таким образом, пустая строка выводится только из стартового нетерминала, однако он по-прежнему может участвовать в формировании правил первого типа. (Это утверждение применимо и к ослабленной нормальной форме Грейбах) <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей функцией для придания грамматике нужного вида:<br />
'''greibah'''(<tex> \Gamma </tex>) <br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \geqslant i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем функцию '''greibah''' для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем функцию '''greibah''' для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>.<br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
== См. также ==<br />
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]<br />
* [[Нормальная_форма_Куроды | Нормальная форма Куроды]]<br />
* [[Нормальная_форма_Хомского | Нормальная форма Хомского]]<br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: Нормальные формы КС-грамматик]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57080Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T21:03:39Z<p>Zernov: </p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. Таким образом, пустая строка выводится только из стартового нетерминала, однако он по-прежнему может участвовать в формировании правил первого типа. (Это утверждение применимо и к ослабленной нормальной форме Грейбах) <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей функцией для придания грамматике нужного вида:<br />
'''greibah'''(<tex> \Gamma </tex>) <br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \geqslant i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем функцию '''greibah''' для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем функцию '''greibah''' для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>.<br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: Нормальные формы КС-грамматик]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57079Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T21:03:20Z<p>Zernov: /* Приведение грамматики к ослабленной нормальной форме Грейбах */</p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. Таким образом, пустая строка выводится только из стартового нетерминала, однако он по-прежнему может участвовать в формировании правил первого типа. (Это утверждение применимо и к ослабленной нормальной форме Грейбах) <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей функцией для придания грамматике нужного вида:<br />
'''greibah'''(<tex> \Gamma </tex>) <br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \geqslant i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем функцию '''greibah''' для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем функцию '''greibah''' для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>.<br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57078Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T21:01:12Z<p>Zernov: </p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. Таким образом, пустая строка выводится только из стартового нетерминала, однако он по-прежнему может участвовать в формировании правил первого типа. (Это утверждение применимо и к ослабленной нормальной форме Грейбах) <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей функцией для придания грамматике нужного вида:<br />
'''greibah'''(<tex> \Gamma </tex>) <br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \ge i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем функцию '''greibah''' для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем функцию '''greibah''' для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>.<br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57077Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T20:55:41Z<p>Zernov: </p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. Таким образом, пустая строка выводится только из стартового нетерминала. Однако он по-прежнему может участвовать в формировании правил первого типа. (Это утверждение применимо и к ослабленной нормальной форме Грейбах) <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
<tex> A \rightarrow a\gamma </tex><br />
<br />
<tex> S \rightarrow \varepsilon </tex><br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей процедурой для придания грамматике нужного вида:<br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \ge i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем процедуру для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем процедуру для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>.<br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57076Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T20:54:11Z<p>Zernov: /* Пример */</p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
* <tex> A \rightarrow a\gamma </tex>,<br />
* <tex> S \rightarrow \varepsilon </tex>,<br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
* <tex> A \rightarrow a\gamma </tex>,<br />
* <tex> S \rightarrow \varepsilon </tex>,<br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей процедурой для придания грамматике нужного вида:<br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \ge i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление стартового нетерминала из правых частей правил<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем процедуру для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем процедуру для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>.<br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D1%8B_%D1%81_%D0%BC%D0%B0%D0%B3%D0%B0%D0%B7%D0%B8%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D1%8C%D1%8E&diff=57075Автоматы с магазинной памятью2016-12-06T20:38:58Z<p>Zernov: </p>
<hr />
<div>==Недетерминированный автомат с магазинной памятью==<br />
{{Определение<br />
|definition= '''Автомат с магазинной памятью''' (автомат со стеком, англ. ''pushdown automaton'') {{---}} это набор <tex>A=\langle\Sigma,\Gamma,Q,s\in Q, T \subset Q, z_0 \in \Gamma, \delta : Q \times \Sigma \cup \{\varepsilon\} \times \Gamma \rightarrow 2^Q \times \Gamma^*\rangle</tex>, где<br />
*<tex>\Sigma</tex> {{---}} входной алфавит на ленте,<br />
*<tex>\Gamma</tex> {{---}} стековый алфавит,<br />
*<tex>Q</tex> {{---}} множество состояний автомата,<br />
*<tex>s</tex> {{---}} стартовое состояние автомата,<br />
*<tex>T</tex> {{---}} множество допускающих состояний автомата,<br />
*<tex>z_0</tex> {{---}} маркер дна стека,<br />
*<tex>\delta</tex> {{---}} функция переходов.<br />
}}<br />
<br />
[[Изображение:PDAsmall.jpg|left|Рис. 1. Автомат с магазинной памятью]]<br />
С ленты последовательно считываются символы входного алфавита (<tex>c_i</tex> {{---}} текущий считываемый символ). Символ <tex>x</tex> снимается с вершины стека. Вместо него помещается строка <tex>\alpha</tex> таким образом, чтобы первый символ строки находился на вершине стека. <br />
<br />
Обычно под автоматом со стеком подразумевается недетерминированный автомат. Заметим, что [[Совпадение множества языков МП-автоматов и контекстно-свободных языков|недетерминированные автоматы со стеком эквивалентны по выразительной мощности контекстно свободным грамматикам.]] Если речь пойдет о [[Детерминированные автоматы с магазинной памятью|детерминированном автомате]], это будет указано отдельно. Заметим также, что [[Несовпадение класса языков, распознаваемых ДМП автоматами и произвольными МП автоматами|детерминированные и недетерминированные автоматы со стеком неэквивалентны]].<br />
<br style="clear:both" /><br />
<br />
==Диаграммы переходов==<br />
<div class="tleft" style="clear:none">[[Файл:Transition1.png|400px|thumb|Рис. 2. Переход: с {{---}} символ, прочитанный с ленты; A {{---}} символ, вынутый из стека; <tex>\alpha</tex> {{---}} строка, помещаемая в стек.]]</div><br />
<div class="tleft" style="clear:none">[[Файл:Transition2.png|400px|thumb|Рис. 3. Переход по любому стековому символу, он же возвращается в стек.]]</div><br />
<div class="tleft" style="clear:none">[[Файл:Transition3.png|400px|thumb|Рис. 4. Переход по любому стековому символу, в стек кладется пустая строка.]]</div><br />
<br style="clear:both" /><br />
По соглашению маркер дна всегда находится на дне (за исключением случая, когда автомат является [[МП-автоматы, допуск по пустому стеку и по допускающему состоянию, эквивалентность|автоматом с допуском по пустому стеку]]). То есть, для <tex>\mathcal8 q \in Q,\mathcal8 c \in \Sigma \cup \{\varepsilon\} \Rightarrow \delta(q, c, z_0) \ni \langle p, \alpha \rangle </tex>, где <tex>p \in Q, \alpha \in \Gamma^*, \alpha = \alpha_1z_0</tex>.<br />
<br />
==Основные определения==<br />
{{Определение<br />
|definition=<br />
'''Мгновенное описание''' {{---}} это набор <tex>\langle q, \alpha, \gamma \rangle</tex>, где <tex>q</tex> {{---}} текущее состояние, <tex>\alpha</tex> {{---}} остаток строки, <tex>\gamma</tex> {{---}} содержимое стека.<br />
}}<br />
{{Определение<br />
|definition=<br />
'''Переход за один шаг''' обозначается как <tex>\langle q, \alpha, \gamma \rangle \vdash \langle r, \beta, \xi \rangle</tex>, где <tex>\alpha = c\beta</tex> (возможно, <tex>c=\varepsilon</tex>), <tex>\gamma = \chi\gamma', \xi = \eta\gamma'</tex>, <tex>\langle r, \eta \rangle \in \delta(q, c, \chi)</tex>.<br />
}}<br />
{{Определение<br />
|definition= '''Язык автомата с магазинной памятью''' <tex>L(A)=\{\alpha \mid \langle s, \alpha, z_0\rangle \vdash^* \langle t, \varepsilon, \gamma \rangle, t \in T\}</tex>.<br />
}}<br />
<br />
==Пример недетерминированного МП-автомата==<br />
[[Изображение:PDAexample.png|300px|thumb|left|Рис. 5. Недетерминированный МП-автомат для языка <tex>0^n1^n</tex>.]]<br style="clear:both" /><br />
<br />
== См. также ==<br />
* [[Детерминированные автоматы с магазинной памятью, допуск по пустому стеку]]<br />
* [[ДМП-автоматы и неоднозначность]]<br />
<br />
== Источники информации ==<br />
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' {{---}} '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2008. — 528 с. : ISBN 978-5-8459-1347-0 (рус.)<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]<br />
[[Категория: МП-автоматы]]</div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:PDAsmall.jpg&diff=57074Файл:PDAsmall.jpg2016-12-06T20:32:26Z<p>Zernov: </p>
<hr />
<div></div>Zernovhttp://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8_%D0%BA_%D0%BE%D1%81%D0%BB%D0%B0%D0%B1%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9_%D1%84%D0%BE%D1%80%D0%BC%D0%B5_%D0%93%D1%80%D0%B5%D0%B9%D0%B1%D0%B0%D1%85&diff=57069Приведение грамматики к ослабленной нормальной форме Грейбах2016-12-06T19:17:33Z<p>Zernov: </p>
<hr />
<div>{{Определение<br />
|definition=Грамматикой в '''нормальной форме Грейбах''' (англ. ''Greibach normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
* <tex> A \rightarrow a\gamma </tex>,<br />
* <tex> S \rightarrow \varepsilon </tex>,<br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из не более, чем двух нетерминалов. <br />
}}<br />
<br />
{{Определение<br />
|definition=Грамматикой в '''ослабленной нормальной форме Грейбах''' (англ. ''Greibach weak normal form'') называется [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободная грамматика]], в которой могут содержаться только правила одного из следующих типов:<br />
* <tex> A \rightarrow a\gamma </tex>,<br />
* <tex> S \rightarrow \varepsilon </tex>,<br />
где <tex> a </tex> {{---}} терминал, <tex> A </tex> {{---}} нетерминал, <tex> S </tex> {{---}} стартовый нетерминал (причём он не должен встречаться в правых частях правил), <tex> \varepsilon </tex> {{---}} пустая строка, <tex> \gamma </tex> {{---}} строка из произвольного числа терминалов и нетерминалов. <br />
}}<br />
<br />
== Приведение грамматики к ослабленной нормальной форме Грейбах ==<br />
{{Теорема<br />
|statement=Любую контекстно-свободную грамматику можно привести к ослабленной нормальной форме Грейбах.<br />
|proof=<br />
Рассмотрим контекстно-свободную грамматику <tex> \Gamma </tex>. Для приведения её к нормальной ослабленной форме Грейбах нужно выполнить три шага. На каждом шаге мы строим новую грамматику, допускающую тот же язык, что и <tex> \Gamma </tex>.<br />
<br />
#Избавимся от <tex> \varepsilon </tex>-правил. Для этого воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]].<br />
#Воспользуемся [[Устранение_левой_рекурсии|алгоритмом устранения левой рекурсии]].Получим грамматику, все правила которой будут иметь следующий вид:<br />
#* <tex> A_i \rightarrow a \gamma </tex>, <br />
#* <tex> A_i \rightarrow A_j \gamma </tex>, где <tex> A_i </tex>, <tex> A_j </tex> {{---}} нетерминалы, <tex> a </tex> {{---}} терминал, <tex> \gamma </tex> {{---}} произвольная последовательность из терминалов и нетерминалов, <tex> i < j </tex>.<br />
#Воспользуемся следующей процедурой для придания грамматике нужного вида:<br />
'''for''' i = n .. 1<br />
'''for''' j = i + 1 .. n<br />
Для каждого правила вывода из <tex> A_j \rightarrow \delta_1 | \ldots | \delta_k </tex> заменить каждое правило <tex> A_i \rightarrow A_j \gamma </tex> на <tex> A_i \rightarrow \delta_1\gamma | \ldots | \delta_k\gamma </tex>.<br />
<br />
После каждой итерации главного цикла все правила для <tex> A_k </tex> (где <tex>k \ge i</tex>) будут иметь вид <tex> A_k \rightarrow a \gamma </tex>.<br />
Значит, после применения процедуры все правила грамматики будут иметь вид <tex> A \rightarrow a \gamma </tex>.<br />
<br />
Таким образом, мы получили грамматику в ослабленной нормальной форме Грейбах, которая допускает тот же язык, что и исходная.<br />
}}<br />
<br />
== Пример ==<br />
{| border="1" class="wikitable" style="width: 500px; height: 500px; float: left;"<br />
!style="background:#41aef0"|Текущий шаг<br />
!style="background:#41aef0"|Грамматика после применения правила<br />
|-<br />
|''0. Исходная грамматика''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''1. Удаление <tex>\varepsilon</tex>-правил''<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow b|SB</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''2. Удаление левой рекурсии (промежуточный шаг)<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|BBB|b</tex> <br> <tex>X\rightarrow b</tex><br> <tex>A\rightarrow a</tex><br />
|-<br />
|''3. Удаление левой рекурсии<br />
|<tex>S\rightarrow XA|BB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''4. Выполняем процедуру для правила <tex>S\rightarrow XA|BB</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow BB|BBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|-<br />
|''5. Выполняем процедуру для правила <tex>Z\rightarrow BB|BBZ</tex><br />
|<tex>S\rightarrow bA|bABB|bB|bABZB|BZB</tex> <br> <tex>B\rightarrow bAB|b|bABZ|bZ</tex> <br> <tex>Z\rightarrow bABB|bB|bABZB|bZB|bABBZ|bBZ|bABZBZ|bZBZ</tex> <br> <tex>X\rightarrow b</tex> <br> <tex>A\rightarrow a</tex><br />
|}<br />
<div style="clear:both;"></div><br />
<br />
<br />
=== Асимптотика ===<br />
<br />
Алгоритм состоит из трех шагов, сложность первого и последнего шага равны <tex>O(\left| \Gamma \right|)</tex> и <tex>O(\left| \Gamma \right| ^ 2)</tex> соответственно. Таким обзом, сложность алгоритма является <tex>O(\left| \Gamma \right| ^ 2) + O\left(n\sum\limits_{i=1}^n a_j\right)</tex>, где второй член {{---}} сложность алгоритма удаления левой рекурсии.<br />
<br />
== Применение ==<br />
'''Простота доказательств'''<br />
<br />
Использование нормальных форм существенно упрощает доказательство теорем. Например, использование нормальной формы Грейбах позволяет доказать, что для каждого контекстно-свободного языка (не содержащего <tex>\varepsilon</tex>) существует автомат с магазинной памятью без переходов по <tex>\varepsilon</tex>.<br />
<br />
'''Разбор грамматики'''<br />
<br />
Нормальная форма Холмского позволяет производить разбор грамматики. Например, с помощью [[Алгоритм Кока-Янгера-Касами разбора грамматики в НФХ|алгоритма Кока-Янгера-Касами]]. В свою очередь, нормальная форма Грейбах позволяет использовать метод рекурсивного спуска, сложность которого является линейной, несмотря на возвраты.<br />
<br />
==Источники информации==<br />
* [[wikipedia:en:Greibach normal form | Wikipedia {{---}} Greibach normal form]]<br />
* [http://www.iitg.ernet.in/gkd/ma513/oct/oct18/note.pdf MA513: Formal Languages and Automata Theory]<br />
<br />
[[Категория: Теория формальных языков]]<br />
[[Категория: Контекстно-свободные грамматики]]</div>Zernov