Языки и их представление
Теорема 2.1. Каждый контекстно-свободный язык может быть порожден неукорачивающей контекстно- свободной грамматикой.
Доказательство. Пусть L - контекстно-свободный язык. Тогда существует контекстно-свободная грамматика G = (N, T, P, S), порождающая L.
Построим новую грамматику G' = (N',T,P',S') следующим образом:
- Если в P есть правило вида
, где
для
и ни из одной цепочки
не выводится e, то включить в P' все правила (кроме
) вида
гдеэто либо
, либо e.
- Если
, то включить в P' правила
и положить
. В противном случае положить
и
. Порождает ли грамматика пустую цепочку можно установить следующим простым алгоритмом:
Шаг 1. Строим множество
Шаг 2. Строим множество
Шаг 3. Если
, перейти к шагу 4, иначе шаг 2.
Шаг 4. Если
, значит
.
Легко видеть, что
- неукорачивающая грамматика. Можно показать по индукции, что
.
Пусть Ki - класс всех языков типа i. Доказано, что
справедливо следующее (строгое) включение: .
Заметим, что если язык порождается некоторой грамматикой, это не означает, что он не может быть порожден грамматикой с более сильными ограничениями на правила. Приводимый ниже пример иллюстрирует этот факт.
Пример 2.8. Рассмотрим грамматику . Эта грамматика является контекстно-свободной. Легко показать, что
. Однако, в примере 2.7 приведена
праволинейная грамматика, порождающая тот же язык.
Ниже приводятся подробные примеры решения двух практически интересных более сложных задач на построение КС- и НС-грамматик.
Пример 2.9. Данный пример относится к несколько парадоксальной для грамматик постановке: построить КС-грамматику, порождающую язык:
![\{\{a,b\}^*\backslash a^n b^m a^n b^m \mid n,m \geq1\}](/sites/default/files/tex_cache/39997ed22ebe3b5328e11f99c22c1536.png)
т.е. построить все цепочки кроме указанных (обычно-то говорят о том, что надо построить). Но, может быть, в такой постановке заложена и подсказка к решению? Известно, что иные задачи с подобными требованиями так и решаются: нужно сделать все, "что не надо", а потом отклониться от этого "не надо" всеми возможными способами.
Однако воодушевлнных построением в рамках КС-
грамматики цепочек вида (здесь и далее в этом
примере
ждет некоторое разочарование.
Действительно, в отличие от таких случаев, как
,
,
и т.п., обе зависимости (по n и по m )
придется отслеживать одновременно и из двух разных центров
порождения, к чему КС-грамматики по своей природе (виду своих
правил) оказываются не предназначены.
Попробуем тогда пересказать условие задачи в конструктивном (созидательном) плане, т.е. обозначая лишь то, что нам нужно построить, а не наоборот. Поначалу такое множество цепочек кажется необозримым. Но попробуем, "Дорогу осилит идущий"! Начнем с очевидных случаев:
![\{a^n\}, \{b^n\}, \{a^n b^m\}, \{b^n a^m\}, \{a^n b^m a^k\}, \{b^n a^m b^k\}\ldots](/sites/default/files/tex_cache/f6c6ed3750bd4612029f62caed55cc76.png)
Однако бесконечно продолжать в духе уже как-
то скучно. Замечаем, что
вполне конечным образом
определяет половину из упомянутых бесчисленных описаний, а в
следующий момент симметрия нам подсказывает и язык
.
Таким образом, все цепочки вышеперечисленных видов укладываются в три случая:
![\{a^n b^m\}, \; b\{a,b\}^*, \; \{a,b\}^*a](/sites/default/files/tex_cache/5a9f429f9d7f302ea0838bcc88a59507.png)
Далее рассмотрим случай . Но что такое, к примеру,
? То же самое, что объединение условий
! И здесь перешли к конструктиву, который несложно строится в рамках КС-грамматики.
Остается единственный неупомянутый случай:
![\{a^n b^m a^k b^l\}a\{a,b\}^*](/sites/default/files/tex_cache/3e9745502a39803c650e7f713fe71658.png)
Вспоминая, что объединение КС-языков есть КС-язык, получаем искомое решение задачи.
Так, если язык может быть порожден грамматикой
![S_1\rightarrow AB](/sites/default/files/tex_cache/d424a32eb7ba5f1ae1b6a3ea07666df4.png)
![A\rightarrow aA \mid a](/sites/default/files/tex_cache/bf6d4d527337ab1df6194e4f9476f2ac.png)
![B\rightarrow bB \mid b](/sites/default/files/tex_cache/5ccb334b10bb7ed3061a6d60d955d4fb.png)
а язык - грамматикой
![S_2 \rightarrow bC](/sites/default/files/tex_cache/59dd5cdda8d2695e689e108b91e011cb.png)
![C \rightarrow CC \mid a \mid b \mid \varepsilon ,](/sites/default/files/tex_cache/a4692aeedecf0365c14a8010b2ab428b.png)
то для объединения этих языков (в общем случае использующих каждый свой уникальный набор вспомогательных знаков) достаточно добавить правило старта из новой общей аксиомы:
![S \rightarrow S_1 \mid S_2](/sites/default/files/tex_cache/e978c742bd785026d6e2df30d91b1a54.png)
Пример 2.10. Построение НС-грамматики.
Грамматики непосредственных составляющих (или, кратко, НС-грамматики) есть вид представления контекстно-зависимых грамматик, т.е. они обладают теми же выразительными возможностями, что и КЗ-грамматики в целом. Каждое правило НС-грамматики должно соответствовать виду:
![\varphi A \psi \rightarrow \varphi\eta\psi, \; (\mid \eta \mid \geq 1)](/sites/default/files/tex_cache/ed4ef1b6e2b0e50056cfd249e3dab42f.png)
то есть левое и правое окружение (контекст) заменяемого знака
A должны сохраниться и вокруг непустой заменяющей цепочки
(греческая буква "эта".
Такое дополнительное ограничение позволяет удобнее переходить от КЗ-грамматики к соответствующему линейно- ограниченному автомату
Рассмотрим построение НС-грамматики для языка
, порождающего слова вида
Для большей ясности сперва построим для этого языка грамматику общего вида, а потом перестроим ее в соответствии с НС-ограничениями.
Сам алгоритм порождения может основываться как на
известном свойстве квадратов чисел, разность между соседними
из которых образуют арифметическую прогрессию, так и на
собственно "квадратности" интересующих чисел, т.е. того, что
каждое квадратное число представимо наподобие матрицы из n
строк и n столбцов единичных элементов (в связи с чем Пифагор
и дал название подобным числам - квадратные, а среди других
чисел по тому же принципу отметил треугольные, кубические,
пирамидальные и т.п.). Последний подход представляется более
общим, поскольку подобным образом мы сможем построить и
.
Итак, порождаем две группы по n элементов
Получили но что делать с C и D? Сделав свое дело, они стали лишними.
В грамматике общего вида такие знаки сокращают
("увольняют"), а в КЗ-грамматиках - "переводят на другую
работу" (в основные знаки). Но если мы просто напишем , вывод в случайный момент времени может закончиться
досрочно и станет возможным порождение лишних цепочек.
Поэтому в обоих случаях не обойтись без дальнейшего уточнения предназначения (миссий) и состава "действующих лиц". Отметим для этого самый первый из команды знаков C (назовем его B ) и самый последний из D (обозначим его E ). Когда B и E встретятся, это и будет признаком полного завершения процесса порождения знаков a.
Начнем вывод с начала:
Правила | Вид получаемой цепочки |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Результат получили, но какой ценой (для B, C, D и E )? Прямо-таки сталинские методы. Точнее скажем, в военных или иных чрезвычайных условиях иначе, порой, и нет возможности поступить. А в более мирное время? Попробуем "соблюдать КЗОТ" и обойтись без сокращений.
Снова: