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

Материал из Викиконспекты
Перейти к: навигация, поиск
(Пример)
Строка 2: Строка 2:
 
{{Определение
 
{{Определение
 
|definition=
 
|definition=
Нетерминал <tex>A</tex> называется '''порождающим''', если из него может быть выведена конечная терминальная цепочка. Иначе он называется '''непорождающим'''.
+
Нетерминал <tex>A</tex> называется '''порождающим''' (''generating''), если из него может быть выведена конечная терминальная цепочка. Иначе он называется '''непорождающим'''.
 
}}
 
}}
  
Очевидно, что если и только если все нетерминалы правой части являются порождающими, то порождающим является и нетерминал, стоящий в левой части. Это позволяет обнаружить непорождающие нетерминалы с помощью следующей процедуры.
+
Очевидно, что если и только если все нетерминалы правой части правила являются порождающими, то порождающим является и нетерминал, стоящий в его левой части. Это позволяет обнаружить непорождающие нетерминалы с помощью следующей процедуры.
 
# Найти правила, не содержащие нетерминалов в правых частях. Составить множество нетерминалов, встречающихся в левых частях таких правил.
 
# Найти правила, не содержащие нетерминалов в правых частях. Составить множество нетерминалов, встречающихся в левых частях таких правил.
 
# Если найдено такое правило, что все нетерминалы, стоящие в его правой части, уже входят в множество, то добавить в множество нетерминалы, стоящие в его левой части.
 
# Если найдено такое правило, что все нетерминалы, стоящие в его правой части, уже входят в множество, то добавить в множество нетерминалы, стоящие в его левой части.
Строка 18: Строка 18:
 
Непорождающие нетерминалы по определению не могли участвовать в выводе какого-либо слова.
 
Непорождающие нетерминалы по определению не могли участвовать в выводе какого-либо слова.
 
}}
 
}}
 +
 +
=== Время работы алгоритма ===
 +
Данный алгоритм работает за <tex>O(\left| \Gamma \right| ^ 2)</tex>, однако, если в грамматике устранены [[Удаление_длинных_правил_из_грамматики|длинные правила]], то используя [[Очередь|очередь]] можно ускорить его до <tex>O(\left| \Gamma \right|)</tex>.
  
 
=== Пример ===
 
=== Пример ===
Строка 25: Строка 28:
 
     S\rightarrow Ac\\
 
     S\rightarrow Ac\\
 
     A\rightarrow SD\\
 
     A\rightarrow SD\\
 +
    D\rightarrow aD\\
 
     A\rightarrow a     
 
     A\rightarrow a     
 
\end{array}
 
\end{array}
 
</tex>
 
</tex>
 
# Изначально множество порождающих нетерминалов состоит из одного элемента <tex>A</tex>.
 
# Изначально множество порождающих нетерминалов состоит из одного элемента <tex>A</tex>.
# Добавим в множество нетеминал <tex>S</tex>, так как существует правило <tex>S\rightarrow Ac</tex>, в правой части которого стоят нетерминал <tex>B</tex>, который есть в множестве, и терминал <tex>c</tex>.
+
# Добавим в множество нетеминал <tex>S</tex>, так как существует правило <tex>S\rightarrow Ac</tex>, в правой части которого стоят нетерминал <tex>A</tex>, который есть в множестве, и терминал <tex>c</tex>.
 
# После следуещего обхода правил из грамматики множество не изменится.
 
# После следуещего обхода правил из грамматики множество не изменится.
# Теперь удалим правило <tex>A\rightarrow SD</tex>, так как оно содержит в правой части нетерминал, которого нет в полученном множестве.
+
# Теперь удалим правила <tex>A\rightarrow SD</tex> и <tex>D\rightarrow aD</tex>, так как они содержит нетерминалы, которых нет в полученном множестве.
  
 
== Достижимые и недостижимые нетерминалы ==
 
== Достижимые и недостижимые нетерминалы ==
 
{{Определение
 
{{Определение
 
|definition=
 
|definition=
Нетерминал <tex>A</tex> называется '''достижимым''' в КС-грамматике <tex>\Gamma</tex>, если существует порождение <tex>S \Rightarrow^* \alpha A \beta</tex>. Иначе он называется '''недостижимым'''.
+
Нетерминал <tex>A</tex> называется '''достижимым''' (''reachable'') в КС-грамматике <tex>\Gamma</tex>, если существует порождение <tex>S \Rightarrow^* \alpha A \beta</tex>. Иначе он называется '''недостижимым''' (''unreachable'').
 
}}
 
}}
  
Строка 44: Строка 48:
 
# Если на шаге 2 множество изменилось, повторить шаг 2.
 
# Если на шаге 2 множество изменилось, повторить шаг 2.
 
# Получено множество всех достижимых нетерминалов, а нетерминалы, не попавшие в него, являются недостижимыми.
 
# Получено множество всех достижимых нетерминалов, а нетерминалы, не попавшие в него, являются недостижимыми.
 
  
 
{{Лемма
 
{{Лемма
Строка 52: Строка 55:
 
Недостижимые нетерминалы по определению не достижимы из стартового, следовательно они не могли участвовать в выводе какого-либо слова.
 
Недостижимые нетерминалы по определению не достижимы из стартового, следовательно они не могли участвовать в выводе какого-либо слова.
 
}}
 
}}
 +
 +
=== Время работы алгоритма ===
 +
Данный алгоритм работает за <tex>O(\left| \Gamma \right| ^ 2)</tex>, однако используя [[Обход_в_глубину,_цвета_вершин|обход в глубину]] можно ускорить его до <tex>O(\left| \Gamma \right|)</tex>.
  
 
=== Пример ===
 
=== Пример ===
Строка 74: Строка 80:
 
{{Определение
 
{{Определение
 
|definition=
 
|definition=
Нетерминал <tex>A</tex> называется '''полезным''' в КС-грамматике <tex>\Gamma</tex>, если он может участвовать в выводе, то есть существует порождение вида <tex>S \Rightarrow ^* \alpha A \beta \Rightarrow ^* w</tex>. Иначе он называется '''бесполезным'''.
+
Нетерминал <tex>A</tex> называется '''полезным''' (''useful'') в КС-грамматике <tex>\Gamma</tex>, если он может участвовать в выводе, то есть существует порождение вида <tex>S \Rightarrow ^* \alpha A \beta \Rightarrow ^* w</tex>. Иначе он называется '''бесполезным''' (''useless'').
 
}}
 
}}
  
Строка 141: Строка 147:
 
</tex>
 
</tex>
 
Все нетерминалы в этой грамматике достижимы. Однако, если удалить <tex>B</tex> как непорождающий, то нетерминал <tex>A</tex> станет недостижимым.
 
Все нетерминалы в этой грамматике достижимы. Однако, если удалить <tex>B</tex> как непорождающий, то нетерминал <tex>A</tex> станет недостижимым.
 +
== См. также  ==
 +
* [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|Контекстно-свободные грамматики]]
 +
* [[Нормальная_форма_Хомского|Нормальная форма Хомского]]
 +
* [http://en.wikipedia.org/wiki/Chomsky_normal_form Chomsky normal form]
  
 
== Литература ==
 
== Литература ==

Версия 01:28, 17 ноября 2013

Порождающие и непорождающие нетерминалы

Определение:
Нетерминал [math]A[/math] называется порождающим (generating), если из него может быть выведена конечная терминальная цепочка. Иначе он называется непорождающим.


Очевидно, что если и только если все нетерминалы правой части правила являются порождающими, то порождающим является и нетерминал, стоящий в его левой части. Это позволяет обнаружить непорождающие нетерминалы с помощью следующей процедуры.

  1. Найти правила, не содержащие нетерминалов в правых частях. Составить множество нетерминалов, встречающихся в левых частях таких правил.
  2. Если найдено такое правило, что все нетерминалы, стоящие в его правой части, уже входят в множество, то добавить в множество нетерминалы, стоящие в его левой части.
  3. Если на шаге 2 множество изменилось, повторить шаг 2.
  4. Получено множество всех порождающих нетерминалов грамматики, а все нетерминалы, не попавшие в него, являются непорождающими.


Лемма:
После удаления из грамматики правил, содержащих непорождающие нетерминалы, язык не изменится.
Доказательство:
[math]\triangleright[/math]
Непорождающие нетерминалы по определению не могли участвовать в выводе какого-либо слова.
[math]\triangleleft[/math]

Время работы алгоритма

Данный алгоритм работает за [math]O(\left| \Gamma \right| ^ 2)[/math], однако, если в грамматике устранены длинные правила, то используя очередь можно ускорить его до [math]O(\left| \Gamma \right|)[/math].

Пример

Рассмотрим грамматику: [math] \begin{array}{l l} S\rightarrow Ac\\ A\rightarrow SD\\ D\rightarrow aD\\ A\rightarrow a \end{array} [/math]

  1. Изначально множество порождающих нетерминалов состоит из одного элемента [math]A[/math].
  2. Добавим в множество нетеминал [math]S[/math], так как существует правило [math]S\rightarrow Ac[/math], в правой части которого стоят нетерминал [math]A[/math], который есть в множестве, и терминал [math]c[/math].
  3. После следуещего обхода правил из грамматики множество не изменится.
  4. Теперь удалим правила [math]A\rightarrow SD[/math] и [math]D\rightarrow aD[/math], так как они содержит нетерминалы, которых нет в полученном множестве.

Достижимые и недостижимые нетерминалы

Определение:
Нетерминал [math]A[/math] называется достижимым (reachable) в КС-грамматике [math]\Gamma[/math], если существует порождение [math]S \Rightarrow^* \alpha A \beta[/math]. Иначе он называется недостижимым (unreachable).


Очевидно, что если нетерминал в левой части правила является достижимым, то и все нетерминалы правой части являются достижимыми. Найти недостижимые нетерминалы можно с помощью следующей процедуры.

  1. Возьмём множество, состоящее из единственного элемента: [math]\lbrace S \rbrace[/math].
  2. Если найдено правило, в левой части которого стоит нетерминал, содержащийся в множестве, добавить в множество все нетерминалы из правой части.
  3. Если на шаге 2 множество изменилось, повторить шаг 2.
  4. Получено множество всех достижимых нетерминалов, а нетерминалы, не попавшие в него, являются недостижимыми.
Лемма:
После удаления из грамматики правил, содержащих недостижимые нетерминалы, язык не изменится.
Доказательство:
[math]\triangleright[/math]
Недостижимые нетерминалы по определению не достижимы из стартового, следовательно они не могли участвовать в выводе какого-либо слова.
[math]\triangleleft[/math]

Время работы алгоритма

Данный алгоритм работает за [math]O(\left| \Gamma \right| ^ 2)[/math], однако используя обход в глубину можно ускорить его до [math]O(\left| \Gamma \right|)[/math].

Пример

Рассмотрим грамматику: [math] \begin{array}{l l} S\rightarrow AB|CD\\ A\rightarrow EF\\ G\rightarrow AD\\ C\rightarrow c \end{array} [/math]

  1. Возьмём множество, состоящее из единственного элемента: [math]\lbrace S \rbrace[/math].
  2. Из [math]S[/math] достижимы нетерминалы [math]A[/math], [math]B[/math], [math]C[/math] и [math]D[/math]. Добавим их в множество и получим [math]\lbrace S, A, B, C, D \rbrace[/math].
  3. Множество изменилось. Переберём заново правила из грамматики. Из [math]A[/math] можно вывести [math]E[/math] и [math]F[/math], добавим их в множество.
  4. Снова переберём правила. Из [math]C[/math] можно вывести только терминал, а [math]G[/math] нету в множестве.
  5. После последнего обхода правил грамматики множество не изменилось, значит мы нашли все достижимые нетерминалы: [math]\lbrace S, A, B, C, D, E, F \rbrace[/math].
  6. Теперь удалим правило [math]G\rightarrow AD[/math], так как оно содержит в левой части нетерминал, которого нет в полученном множестве.

Полезные и бесполезные нетерминалы

Определение:
Нетерминал [math]A[/math] называется полезным (useful) в КС-грамматике [math]\Gamma[/math], если он может участвовать в выводе, то есть существует порождение вида [math]S \Rightarrow ^* \alpha A \beta \Rightarrow ^* w[/math]. Иначе он называется бесполезным (useless).


Теорема:
Грамматика [math]\Gamma[/math] не содержит бесполезных нетерминалов тогда и только тогда, когда грамматика [math]\Gamma[/math] не содержит ни недостижимых нетерминалов, ни непорождающих.
Доказательство:
[math]\triangleright[/math]

Необходимость. Очевидно, так как недостижимые и непорождающие нетерминалы являются бесполезными.

Достаточность. Рассмотрим любой нетерминал [math]A[/math]. Так как он достижим, существуют [math]\alpha[/math] и [math]\beta[/math] такие, что [math]S \Rightarrow ^* \alpha A \beta[/math]. Из того, что любой нетерминал является порождающим, следует, что из любой строки можно вывести строку из терминалов. Значит, существует [math]\omega \in \Sigma ^ *[/math]: [math]S \Rightarrow ^* \alpha A \beta \Rightarrow ^* \omega[/math], и [math]A[/math] — не бесполезный.
[math]\triangleleft[/math]

Алгоритм удаления бесполезных нетерминалов

  1. Удалить из грамматики правила, содержащие непорождающие нетерминалы.
  2. Удалить из грамматики правила, содержащие недостижимые нетерминалы.

Корректность алгоритма

Достаточность данных действий следует из доказанной выше теоремы.

Докажем, что после выполнения второго шага не могут появиться новые непорождающие нетерминалы.

Допустим, что в грамматике появился непорождающий нетерминал [math]A[/math]. Так как до удаления недостижимых нетерминалов существовал вывод из [math]A[/math] некоторой конечной цепочки терминалов [math]\omega[/math], то было удалено хотя бы какое-то одно правило из этого вывода.

Пусть [math]B\rightarrow\alpha[/math] — правило, первым из удалённых применяемое в выводе [math]A \Rightarrow ^* \omega[/math]. Оно могло быть удалено только в том случае, если в [math]\alpha[/math] присутствуют недостижимые нетерминалы. Но так как было выбрано первое удалённое правило из вывода, то [math]B[/math] — достижим, следовательно достижимы и все нетерминалы из [math]\alpha[/math]. Значит, это правило не могло быть удалено.

Пример

Пусть нам дана грамматика: [math] \begin{array}{l l} S\rightarrow AS|BS|s \\ E\rightarrow EF|FF \\ A\rightarrow a \\ F\rightarrow f \end{array} [/math].
Удалим правила, содержащие непорождающие нетерминалы и получим грамматику [math] \begin{array}{l l} S\rightarrow AS|s \\ E\rightarrow EF|FF \\ A\rightarrow a \\ F\rightarrow f \end{array} [/math].
Теперь удалим недостижимые нетерминалы и получим грамматику [math] \begin{array}{l l} S\rightarrow AS|s \\ A\rightarrow a \end{array} [/math].

Замечание

Шаги алгоритма нельзя менять местами.

Рассмотрим следующую грамматику: [math] \begin{array}{l l} S\rightarrow AB|a \\ A\rightarrow b \end{array}. [/math] Все нетерминалы в этой грамматике достижимы. Однако, если удалить [math]B[/math] как непорождающий, то нетерминал [math]A[/math] станет недостижимым.

См. также

Литература

  • Хопкрофт Д., Мотвани Р., Ульман Д.Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)