Изменения

Перейти к: навигация, поиск

Удаление бесполезных символов из грамматики

7094 байта добавлено, 19:21, 4 сентября 2022
м
rollbackEdits.php mass rollback
== Порождающие и непорождающие нетерминалы ==
===Описание===
{{Определение
|definition=
Символ '''[[Формальные_грамматики|Нетерминал]] <tex>A</tex>называется '''порождающим' называется ''(англ. 'непорождающим'generating''), если из него не может быть выведена конечная терминальная цепочка. Иначе он называется '''непорождающим'''.
}}
Очевидно, что если и только если все нетерминалы правой части правила являются порождающими, то порождающим является и нетерминал, стоящий в его левой части.
{{Лемма
|statement=
После удаления из грамматики правил, содержащих непорождающие нетерминалы, язык не изменится.
|proof=
Непорождающие нетерминалы по определению не могли участвовать в выводе какого-либо слова.
}}
 
===Алгоритм===
'''Шаг 0'''. Множество порождающих нетерминалов пустое.<br>
'''Шаг 1'''. Находим правила, не содержащие нетерминалов в правых частях и добавляем нетерминалы, встречающихся в левых частях таких правил, в множество.<br>
'''Шаг 2'''. Если найдено такое правило, что все нетерминалы, стоящие в его правой части, уже входят в множество, то добавим в множество нетерминалы, стоящие в его левой части. <br>
'''Шаг 3'''. Повторим предыдущий шаг, если множество порождающих нетерминалов изменилось.<br>
В результате получаем множество всех порождающих нетерминалов грамматики, а все нетерминалы, не попавшие в него, являются непорождающими.
Рассматривая правила грамматики, можно сделать вывод, что если и только если все нетерминальные символы правой части являются порождающими, то порождающим является и символ, стоящий в левой части. Последнее утверждение позволяет написать процедуру обнаружения непорождающих символов в следующем виде: === Время работы алгоритма ===# Составить список нетерминаловДанный алгоритм работает за <tex>O(\left| \Gamma \right| ^ 2)</tex>, для которых найдется хотя бы одно правило, правая часть которого не содержит нетерминаловгде <tex>\left| \Gamma \right|</tex> {{---}} размер грамматики. # Если найдено такое правило, что все нетерминалы, стоящие в его правой части уже занесены в список, то добавить в список нетерминал, стоящий в Однако используя [[Очередь|очередь]] можно ускорить его левой части. # Если на шаге 2 список больше не пополняется, то получен список всех порождающих нетерминалов грамматики, а все нетерминалы, не попавшие в него, являются непорождающимидо <tex>O(\left| \Gamma \right|)</tex>.
===Модификация алгоритма с очередью===
Для реализации алгоритма поиска непорождающих нетерминалов будем использовать следующие структуры:
*<tex>\mathrm{isGenerating[nonterm_i]}</tex> {{---}} является ли нетерминал <tex>\mathrm{nonterm_i}</tex> порождающим или нет,
*<tex>\mathrm{counter[rule_i]}</tex> {{---}} счетчик количества нетерминалов, которые ещё не помечены порождающими, для каждого из правил,
*<tex>\mathrm{concernedRules[nonterm_i]}</tex> {{---}} для каждого нетерминала <tex>\mathrm{nonterm_i}</tex> список номеров правил, в правой части которых он встречается,
*<tex>\mathrm{Q}</tex> {{---}} очередь нетерминалов, помеченных порождающими, но ещё не обработанных.
 
Вначале для всех нетерминалов в <tex>\mathrm{isGenerating}</tex> поставим <tex>false</tex>. В <tex>\mathrm{counter}</tex> поставим количество нетерминалов в правой части. Нетерминалы, у которых счётчик <tex>\mathrm{counter}</tex> нулевой, добавим в очередь и отметим их порождающими.<br>
Пока в очереди есть элементы, достаём очередной нетерминал и уменьшаем <tex>\mathrm{counter}</tex> для всех правил из <tex>\mathrm{concernedRules}</tex> для данного нетерминала. Если счётчик количества порождающих терминалов обнулился, то добавим нетерминал, стоящий в левой части данного правила в очередь и пометим его порождающим.<br>
Каждый из нетерминалов попадёт в очередь только один раз, следовательно мы пройдем по списку правил, в правой части которых он встречается, один раз. Таким образом, суммарно получаем <tex>O(\left| \Gamma \right|)</tex>.
 
=== Пример ===
Рассмотрим следующую грамматику: <br>
 
:<tex>
S\rightarrow Ac\\
A\rightarrow SD\\
D\rightarrow aD\\
A\rightarrow a
</tex>
Применяя описанный алгоритм:
# Изначально множество порождающих нетерминалов состоит из одного элемента <tex>A</tex>.
# Добавим в множество нетерминал <tex>S</tex>, так как существует правило <tex>S\rightarrow Ac</tex>, в правой части которого стоят нетерминал <tex>A</tex>, который есть в множестве, и терминал <tex>c</tex>.
# После следующего обхода правил из грамматики множество не изменится.
# Теперь удалим правила <tex>A\rightarrow SD</tex> и <tex>D\rightarrow aD</tex>, так как они содержат нетерминалы, которых нет в полученном множестве.
 
== Достижимые и недостижимые нетерминалы ==
===Описание===
{{Определение
|definition=
Символ '''Нетерминал <tex>A</tex>называется ''' называется достижимым'''(англ. 'недостижимым'reachable'' ) в [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|КС-грамматике ''']] <tex>\Gamma</tex>''', если строку, содержащую '''существует порождение <tex>S \Rightarrow^* \alpha A\beta</tex>. Иначе он называется '''недостижимым''' (англ. ''unreachable'').}}Очевидно, что если нетерминал в левой части правила является достижимым, то и все нетерминалы правой части являются достижимыми. {{Лемма|statement=После удаления из грамматики правил, нельзя вывести содержащих недостижимые нетерминалы, язык не изменится.|proof=Недостижимые нетерминалы по определению не достижимы из стартового нетерминала, следовательно они не могли участвовать в выводе какого-либо слова.
}}
===Алгоритм===
'''Шаг 0.''' Множество достижимых нетерминалов состоит из единственного элемента: <tex>\lbrace S \rbrace</tex>.<br>
'''Шаг 1.''' Если найдено правило, в левой части которого стоит нетерминал, содержащийся в множестве, добавим в множество все нетерминалы из правой части.<br>
'''Шаг 2.''' Повторим предыдущий шаг, если множество порождающих нетерминалов изменилось.<br>
Получаем множество всех достижимых нетерминалов, а нетерминалы, не попавшие в него, являются недостижимыми.
 
=== Время работы алгоритма ===
Данный алгоритм работает за <tex>O(\left| \Gamma \right| ^ 2)</tex>, однако используя [[Обход_в_глубину,_цвета_вершин|обход в глубину]] можно ускорить его до <tex>O(\left| \Gamma \right|)</tex>.
Рассматривая правила грамматики, можно заметить , что если нетерминал в левой части правила является достижимым , то и все символы правой части являются достижимыми. Это свойство правил является основой процедуры выявления недостижимых символов, которую можно записать так=== Пример ===Рассмотрим следующую грамматику: # Образовать одноэлементный список, состоящий из начального символа # Если найдено правило, левая часть которого уже имеется в списке, то включить в список все символы, содержащиеся в его правой части. # Если на шаге 2 новые нетерминалы в список больше не добавляются, то получен список всех достижимых нетерминалов, а нетерминалы, не попавшие в список, являются недостижимыми. <br>
:<tex>
S\rightarrow AB|CD\\
A\rightarrow EF\\
G\rightarrow AD\\
C\rightarrow c
</tex>
Применяя описанный алгоритм:
# Возьмём множество, состоящее из единственного элемента: <tex>\lbrace S \rbrace</tex>.
# Из <tex>S</tex> достижимы нетерминалы <tex>A</tex>, <tex>B</tex>, <tex>C</tex> и <tex>D</tex>. Добавим их в множество и получим <tex>\lbrace S, A, B, C, D \rbrace</tex>.
# Множество изменилось. Переберём заново правила из грамматики. Из <tex>A</tex> можно вывести <tex>E</tex> и <tex>F</tex>, добавим их в множество.
# Снова переберём правила. Из <tex>C</tex> можно вывести только терминал, а <tex>G</tex> нет в множестве.
# После последнего обхода правил грамматики множество не изменилось, значит мы нашли все достижимые нетерминалы: <tex>\lbrace S, A, B, C, D, E, F \rbrace</tex>.
# Теперь удалим правило <tex>G\rightarrow AD</tex>, так как оно содержит в левой части нетерминал, которого нет в полученном множестве.
 
== Полезные и бесполезные нетерминалы ==
===Описание===
{{Определение
|definition=
Символ '''Нетерминал <tex>A</tex>называется ''' называется полезным'''бесполезным(англ. ''useful'' ) в КС-грамматике '''<tex>\Gamma</tex>''', если он не может встретиться участвовать в выводе слова из терминалов. То , то есть не существует порождения порождение вида <tex>S \Rightarrow ^* \alpha A \beta \Rightarrow ^* w</tex>, где <tex>w</tex> {{---}} строка терминалов. Иначе он называется '''бесполезным''' (англ. ''useless'').
}}
 
{{Теорема
|id=th1
|statement=
Грамматика <tex>\Gamma</tex> не содержит бесполезных символов '''нетерминалов тогда и только тогда, когда''' она грамматика <tex>\Gamma</tex> не содержит ни недостижимых символовнетерминалов, ни непорождающих.
|proof=
<tex>\RightarrowLeftarrow</tex> <br/>:Очевидно, т.к. так как недостижимые и непорождающие символы нетерминалы являются бесполезными. <tex>\LeftarrowRightarrow</tex> <br/>:Рассмотрим любой нетерминал <tex>A</tex>. Так как он достижимыйдостижим, существуют <tex>\alpha</tex> и <tex>\beta</tex>, такие, что <tex>S \Rightarrow ^* \alpha A \beta</tex>. Из того, что любой сивол нетерминал является порождающим, следует, что из любой строки можно вывести строку из терминалов. Значит, существует <tex>\omega \in \Sigma ^ *</tex>: <tex>S \Rightarrow ^* \alpha A \beta \Rightarrow ^* \omega</tex>, и <tex>A</tex> {{--- }} не бесполезный.
}}
===Алгоритм===
Алгоритм состоит из двух этапов:
# Удалить из грамматики правила, содержащие непорождающие нетерминалы.
# Удалить из грамматики правила, содержащие недостижимые нетерминалы.
 
=== Корректность алгоритма ===
Достаточность данных действий следует из доказанной выше теоремы.
{{Теорема
|id=th2th1
|statement=
Пусть После удаления из грамматики правил, содержащих недостижимые нетерминалы, не появятся новые непорождающие нетерминалы.|proof=Допустим, что в грамматике появился непорождающий нетерминал <tex>GA</tex> {{---}} КС-грамматика, и . Так как до удаления недостижимых нетерминалов существовал вывод из <tex>L(G)\ne\varnothingA</tex>. Пусть некоторой конечной цепочки терминалов <tex>G_1\omega</tex> , то было удалено хотя бы какое- грамматика, полученная с помощью следующих двух шагов:то одно правило из этого вывода.
1) Удаляются непорождающие символы и все продукции, содержащие один или несколько таких символов. Пусть <tex>G_2B\rightarrow\alpha</tex> {{---}} полученная правило, первым из удалённых применяемое в результате грамматикавыводе <tex>A \Rightarrow ^* \omega</tex>. Оно могло быть удалено только в том случае, если в <tex>\alpha</tex> присутствуют недостижимые нетерминалы.Но так как было выбрано первое удалённое правило из вывода, то <tex>B</tex> — достижим, следовательно достижимы и все нетерминалы из <tex>\alpha</tex>. Значит, это правило не могло быть удалено.}}
2) Удаляются все символы, недостижимые из <tex>G_2</tex>.=== Пример ===
Тогда <tex>G_1</tex> не имеет бесполезных символов и <tex>L(G_1)=L(G)</tex>1.|proof=Пусть нам дана грамматика: <tex>X</texbr> {{---}} оставшийся символ. Известно, что <tex>X\Rightarrow _G^* w</tex> для некоторой цепочки <tex>w</tex> из терминалов. Кроме того, каждый символ, использованный в этом порождении, достижим, поэтому <tex>S\Rightarrow _{G_2}^* w</tex>.
Поскольку <tex>X</tex> не был удален на втором шаге, известно, что существует такие :<tex> S\rightarrow AS|BS|s \\ E\rightarrow EF|FF \\alpha</tex> и <tex> A\beta</tex>, для которых <tex>Srightarrow a \Rightarrow _{G_2}^* \alpha X F\betarightarrow f</tex><br>2. Кроме тогоУдалим правила, каждый символ, использованный в этом порождении, достижим, поэтому содержащие непорождающие нетерминалы: <texbr>S\Rightarrow _{G_1}^* \alpha X\beta</tex>.
Также известно, что каждый символ в цепочке :<tex> S\rightarrow AS|s \\alpha X E\rightarrow EF|FF \beta</tex> достижим, поэтому каждый из них является порождающим в <tex>G_2</tex>. Порождение некоторой терминальной цепочки, например, <tex>\alpha X A\betarightarrow a \Rightarrow _{G_2}^* xwy</tex>, содержит только символы, достижимые из <tex>S</tex>, поскольку они достижимы из символов в цепочке <tex>\alpha X F\betarightarrow f</tex>. Таким образом, это порождение есть также порождение в <texbr>G_1</tex>, то есть 3. Теперь удалим недостижимые нетерминалы:<texbr>S\Rightarrow _{G_1}^* \alpha X\beta\Rightarrow _{G_1}^* xwy</tex>.
Итак, :<tex>X</tex> полезен в <tex>G_1</tex>. Ввиду произвольности <tex>X</tex> в <tex>G_1</tex> можно заключить, что <tex>G_1</tex> не имеет бесполезных символов. <tex>L(G_1) S\subseteq L(G)</tex>, так как при построении <tex>G_1</tex> из <tex>G</tex> символы и продукции только убирались. Докажем, что <tex>L(G_1)rightarrow AS|s \supseteq L(G)</tex>. Если <tex>w\in L(G)</tex>, то <tex>S A\Rightarrow _{G}^* wrightarrow a</tex>. Каждый символ в этом порождении является как достижимым, так и порождающим, поэтому порождение в <tex>G_1</tex> его также содержит. Таким образом, <tex>S\Rightarrow _{G_1}^* w</tex>, <tex>w\in L(G_1)</tex> и <tex>L(G)=L(G_1)</tex>.}}
''Примечание:''=== Замечание ===Шаги алгоритма нельзя менять местами.
Эти шаги нельзя менять местами. Рассмотрим следующую грамматику:<br>
:<tex> S\rightarrow AB|a \\ A\rightarrow b</tex>
Все нетерминалы в этой грамматике достижимы. Однако, если удалить <tex>B</tex> как непорождающий, то нетерминал <tex>A\rightarrow b</tex>станет недостижимым.== См. также ==* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]
Если начать == Источники информации ==* [[wikipedia:Formal_grammar | Wikipedia {{---}} Formal grammar]]* [http://en.wikipedia.org/wiki/Chomsky_normal_form Wikipedia {{---}} Chomsky normal form]* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' {{---}} Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с проверки достижимостиангл. — Москва, Издательский дом «Вильямс», то все символы грамматики оказываются достижимыми2002. Если затем удалить <tex>B</tex> как непорождающий символ, то останется грамматика — 528 с бесполезными символами <tex>A</tex> и <tex>b</tex>.: ISBN 5-8459-0261-4 (рус.)
== Литература ==[[Категория: Теория формальных языков]]* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' — '''Введение в теорию автоматов, языков и вычислений''', 2[[Категория: Контекстно-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. свободные грамматики]][[Категория: ISBN 5-8459-0261Нормальные формы КС-4 (рус.)грамматик]]
1632
правки

Навигация