ГЛАВА 7
Свойства контекстно- свободных языков
Наше изучение контекстно-свободных языков завершается знакомством с некоторыми из их свойств. Вначале определяются ограничения на структуру продукций КС-грамматик и доказывается, что всякий КС-язык имеет грамматику специального вида. Этот факт облегчает доказательство утверждений о КС-языках.
Затем доказывается «лемма о накачке» для КС-языков. Эта теорема аналогична теореме 4.1 для регулярных языков, но может быть использована для доказательства того, что некоторые языки не являются контекстно-свободными. Далее рассматриваются свойства, изученные в главе 4 для регулярных языков, — свойства замкнутости и разрешимости. Показывается, что некоторые, но не все, свойства замкнутости регулярных языков сохраняются и у КС-языков. Часть задач, связанных с КС-языками, разрешается с помощью обобщения проверок, построенных для регулярных языков, но есть и ряд вопросов о КС-языках, на которые нельзя дать ответ.
7.1. Нормальные формы контекстно-свободных грамматик
Цель этого раздела — показать, что каждый КС-язык (без £) порождается грамматикой, все продукции которой имеют форму А —> ВС или А а, где А, В и С— переменные, а — терминал. Эта форма называется нормальной формой Хомского. Для ее получения нужно несколько предварительных преобразований, имеющих самостоятельное значение.
- Удалить бесполезные символы, т.е. переменные или терминалы, которые не встречаются в порождениях терминальных цепочек из стартового символа.
- Удалить е-продукции, т.е. продукции вида А —» £ для некоторой переменной А.
- Удалить цепные продукции вида А —> В с переменными Aw В.
7.1.1. Удаление бесполезных символов
Символ X называется полезным в грамматике G = (V, Т, Р, S), если существует неко- * *
торое порождение вида S => аХр => w, где w е Т». Отметим, что X может быть как переменной, так и терминалом, а выводимая цепочка аХР— первой или последней в порождении. Если символ X не является полезным, то называется бесполезным. Очевидно, что исключение бесполезных символов из грамматики не изменяет порождаемого языка, поэтому все бесполезные символы можно обнаружить и удалить.
Наш подход к удалению бесполезных символов начинается с определения двух свойств, присущих полезным символам.
- Символ X называется порождающим, если X => w для некоторой терминальной цепочки Заметим, что каждый терминал является порождающим, поскольку w может быть этим терминалом, порождаемым за 0 шагов.
*
- Символ X называется достижимым, если существует порождение S => схХ(3 для некоторых а и р.
Естественно, что полезный символ является одновременно и порождающим, и достижимым. Если сначала удалить из грамматики непорождающие символы, а затем недостижимые, то, как будет доказано, останутся только полезные. Пример 7.1. Рассмотрим следующую грамматику.
S-> АВ | а А^Ь
Все символы, кроме В, являются порождающими; а и b порождают самих себя, 5 порождает а и А порождает Ь. Если удалить В, то придется удалить и продукцию S —> АВ, что приводит к следующей грамматике.
S->a A—>b
Теперь нетрудно обнаружить, что из S достижимы только а и S. Удаление А и b оставляет лишь продукцию S —> а. Она образует грамматику с языком {а}, как и у исходной грамматики.
Заметим, что если начать с проверки достижимости, то все символы грамматики
S АВ | а А-^Ь
оказываются достижимыми. Если затем удалить В как непорождающий символ, то останется грамматика с бесполезными символами А и Ь. О
Теорема 7.2. Пусть G = (V, Т, Р, S) — КС-грамматика, и L(G) t 0, т.е. G порождает хотя бы одну цепочку. Пусть G, = (УЛ Th Р,, S)— грамматика, полученная с помощью следующих двух шагов.
- Вначале удаляются непорождающие символы и все продукции, содержащие один или несколько таких символов. Пусть G7 = (V2, Т2, Р2, S) — полученная в результате грамматика. Заметим, что S должен быть порождающим, так как по предположению L(G) содержит хотя бы одну цепочку, поэтому S не удаляется.
- Затем удаляются все символы, недостижимые в G2. Тогда G; не имеет бесполезных символов, и L(Gi) = L(G).
Доказательство. Пусть X— оставшийся символ, т.е. Хе Т] U Vh Нам известно, что
X => w для некоторой цепочки w из Т*. Кроме того, каждый символ, использованный в
порождении w из X, также является порождающим. Таким образом, X => w.
Поскольку X не был удален на втором шаге, нам также известно, что существуют такие а и Д для которых S => аХр. Кроме того, каждый символ, использованный в этом
*
порождении, достижим, поэтому S => aXfi.
Gi
Нам известно, что каждый символ в цепочке aXfi достижим, и что все эти символы принадлежат Т2 U V2, поэтому каждый из них является порождающим в G2. Порождение
некоторой терминальной цепочки, скажем, аХ/З => xwy, содержит только символы, дос-
Gz
тижимые из S, поскольку они достижимы из символов в цепочке схХ{5. Таким образом, это порождение есть также порождение в G/, т.е.
S => аХв => xwy.
g, ^ g,
Итак, X полезен в С/. Ввиду произвольности X в G/ можно заключить, что G/ не имеет бесполезных символов.
Нам осталось доказать, что L(G,) = L(G). Как обычно, покажем взаимное включение этих языков.
Включение L(G;)cL(G) очевидно, поскольку при построении Gt из G символы и продукции только удаляются.
Докажем, что L(G) с ЦС,). Если w е L(G), то S => w. Каждый символ в этом порож-
G
дении, очевидно, является как достижимым, так и порождающим, поэтому порождение в Gi также его содержит. Таким образом, S => w, и w е L(G,). □
7.1.2. Вычисление порождающих и достижимых символов
Рассмотрим, каким образом вычисляются множества порождающих и достижимых символов грамматики. В алгоритме, используемом в обеих задачах, делается максимум возможного, чтобы обнаружить символы этих двух типов. Докажем, что если правильное индуктивное построение указанных множеств не позволяет обнаружить, что символ является, порождающим или достижимым, то он не является символом соответствующего типа.
Базис. Каждый символ из Т, очевидно, является порождающим; он порождает сам себя.
Индукция. Предположим, есть продукция А —> а, и известно, что каждый символ в а является порождающим. Тогда А — порождающий. Заметим, что это правило включает и случай, когда а = е; все переменные, имеющие в в качестве тела продукции, являются порождающими.
Пример 7.3. Рассмотрим грамматику из примера 7.1. Согласно базису а и b — порождающие. По индукции используем продукции А —> b и S —> а, чтобы заключить, что А и S — также порождающие. На этом индукция заканчивается. Продукцию S —» АВ использовать нельзя, поскольку не установлено, что В — порождающий. Таким образом, множеством порождающих символов является {a, b, A, S}. □
Теорема 7.4. Вышеприведенный алгоритм находит все порождающие символы грамматики G и только их.
Доказательство. В одну сторону, а именно, что каждый добавленный символ на самом деле является порождающим, доказать легко с помощью индукции по порядку, в котором символы добавляются к множеству порождающих символов. Это оставляется в качестве упражнения.
Для доказательства в другую сторону предположим, что X— порождающий, и пусть X => vf. Докажем индукцией по длине порождения, что X будет обнаружен как порождающий.
Базис. Нуль шагов. Тогда X— терминал и находится как порождающий согласно базису алгоритма.
Индукция. Если порождение имеет п шагов, где п > 0, то X— переменная. Пусть порождение имеет вид X =» а => vv, т.е. первой использована продукция X -> а. Из
каждого символа цепочки а выводится некоторая терминальная цепочка, образующая часть w, и это порождение имеет менее, чем п шагов. По предположению индукции каждый символ цепочки а находится как порождающий. Индуктивная часть алгоритма позволяет с помощью продукции Х—> а заключить, что X— порождающий. □
Теперь рассмотрим индуктивный алгоритм, с помощью которого находится множество достижимых символов грамматики G = (V, Т, Р, S). Можно доказать, что если символ не добавляется к множеству достижимых символов путем максимально возможного обнаружения, то он не является достижимым.
Базис. Очевидно, что S действительно достижим.
Индукция. Пусть обнаружено, что некоторая переменная А достижима. Тогда для всех продукций с головой А все символы тел этих продукций также достижимы.
Пример 7.5. Снова начнем с грамматики из примера 7.1. Согласно базису S достижим. Поскольку S имеет тела продукций АВ и а, символы А, В и а также достижимы. У В продукций нет, но А имеет А —» Ь. Делаем вывод, что b достижим. К множеству достижимых символов {S, А, В, а, Ь) добавить больше нечего. □
Теорема 7.6. Вышеприведенный алгоритм находит все достижимые символы грамматики G, и только их.
Доказательство. Это доказательство представляет собой еще одну пару простых индукций в духе теоремы 7.4 и оставляется в качестве упражнения.
7.1.3. Удаление е-продукций
Покажем теперь, что е-продукции, хотя и удобны в задачах построения грамматик, не являются существенными. Конечно же, без продукции с телом £ невозможно породить лустую цепочку как элемент языка. Таким образом, в действительности доказывается, что если L задается КС-грамматикой, то L — {£} имеет КС-грамматику без е-продукций. Начнем с обнаружения «£-порождающих» переменных. Переменная А называется
Е-порождающей, если А => £. Если А — £-порождающая, то где бы в продукциях она ни встречалась, например в В —> CAD, из нее можно (но не обязательно) вывести £. Продукция с такой переменной имеет еще одну версию без этой переменной в теле (В —> CD). Эта версия соответствует тому, что £-порождающая переменная использована для вывода е. Используя версию В —» CAD, мы не разрешаем из А выводить £. Это не создает проблем, так как далее мы просто удалим все продукции с телом £, предохраняя каждую переменную от порождения £.
Пусть G = (V, Т, P,S) — КС-грамматика. Все £-порождающие символы G можно найти с помощью следующего алгоритма. Далее будет показано, что других £-порождающих символов, кроме найденных алгоритмом, нет.
Базис. Если А -> £— продукция в G, то А — £-порождающая.
Индукция. Если в G есть продукция В —> С/С2…Сь где каждый символ С, является £-порождающим, то В — £-порождающая. Отметим, что для того, чтобы С, был ^порождающим, он должен быть переменной, поэтому нам нужно рассматривать продукции, тела которых содержат только переменные.
Теорема 7.7. В любой грамматике ^-порождающими являются только переменные, найденные вышеприведенным алгоритмом.
Доказательство. Переформулируем утверждение в виде «А является £-порождающей тогда и только тогда, когда алгоритм идентифицирует А как е-порождающую». Для достаточности нетрудно показать индукцией по порядку, в котором обнаруживаются £-
порождающие символы, что каждый такой символ действительно порождает £. Для не-
*
обходимости используем индукцию по длине кратчайшего порождения А ==> £.
Базис. Один шаг. Тогда А —> £ должно быть продукцией, и А обнаруживается согласно базису алгоритма.
Индукция. Пусть А => £ за п шагов, где п> 1. Первый шаг должен иметь вид А=> CiC2.—Ck => £, где каждый символ С, порождает £ за число шагов, которое
меньше п. По предположению индукции каждый символ С, обнаруживается как е-порож- дающий. Тогда с помощью индуктивного шага А также обнаруживается как е-по- рождающая на основе продукции А —> С/Сг-.-С*. □
Пример 7.8. Рассмотрим следующую грамматику. S —»АВ А —> аАА | е В^ЬВВ \е
Сначала найдем е-порождающие символы. А и В непосредственно е-порождающие, так как имеют продукции сев качестве тела. Тогда и S е-порождающий, поскольку тело продукции S —> АВ состоит только из е-порождающих символов. Таким образом, все три переменные являются е-порождающими.
Построим теперь продукции грамматики G/. Сначала рассмотрим S —»АВ. Все символы тела являются е-порождающими, поэтому есть 4 способа выбрать присутствие или отсутствие А и В. Однако нам нельзя удалять все символы одновременно, поэтому получаем следующие три продукции.
S^AB\A\B
Далее рассмотрим продукцию А —> аАА. Вторую и третью позиции занимают е-по- рождающие символы, поэтому снова есть 4 варианта их присутствия или отсутствия. Все они допустимы, поскольку в любом из них остается терминал а. Два из них совпадают, поэтому в грамматике G/ будут следующие три продукции.
А —> аАА | аА | а
Аналогично, продукция для В приводит к следующим продукциям в G/. В —> ЪВВ\bB\b
Обе е-продукции из G не вносят в G, ничего. Таким образом, следующие продукции образуют G/.
S^AB\А\В А —> аАА \aA\a В ЬВВ \bB\b
□
Завершим наше изучение удаления е-продукций доказательством, что описанная конструкция не изменяет язык, за исключением того, что цепочки е в нем больше нет, если она была в языке грамматики G. Поскольку конструкция, очевидно, удаляет е-продукции, мы будем иметь полное доказательство утверждения о том, что для любой КС-грамматики G найдется такая КС-грамматика G; без е-продукций, для которой
L(G;) = L(G)-{£}-
Теорема 7.9. Если грамматика G/ построена по грамматике G с помощью описанной выше конструкции удаления е-продукций, то I(G;) = L(G) — {е}.
Доказательство. Нужно доказать, что если w Ф е, то w е L(Gj) тогда и только тогда, когда w е ЦС). Как часто случается, проще доказать более общее утверждение. В данном случае будем говорить о терминальных цепочках, порождаемых каждой переменной, несмотря на то, что нас интересуют лишь порождаемые стартовым символом S. Таким образом, докажем следующее утверждение.
- А => w тогда и только тогда, когда А => w и w * е.
с, а
В обе стороны доказательство проводится индукцией по длине порождения. (Необходимость) Пусть А => w. Несомненно,
w Ф е, поскольку Cjj не имеет е-
О]
продукций. Докажем индукцией по длине порождения, что А => w.
G
Базис. Один шаг. В этом случае в Gt есть продукция А —» w. Согласно конструкции G/ в G есть продукция А а, причем а— это w, символы которой, возможно, перемежаются ^-порождающими переменными. Тогда в G есть порождение А => а => w, где на
G G
шагах после первого, если они есть, из всех переменных в цепочке а выводится е.
Индукция. Пусть в порождении п шагов, п> 1. Тогда оно имеет вид
А => Х,Х2.. .Хк => w. Первая использованная продукция должна быть построена по про-
g, (j,
дукции А Y/Y2…Ym, где цепочка Y,Y2…Ym совпадает с цепочкой XtX2..Хк, символы которой, возможно, перемежаются дополнительными е-порождающими переменными. Цепочку w можно разбить на w:w2…wk, где X, => w, для / = 1, 2, …, к. Если X, есть терми-
нал, то w, = Х„ а если переменная, то порождение Xj => w, содержит менее п шагов. По
*
предположению индукции X, w,.
Теперь построим соответствующее порождение в G.
А Y,Y2…Ym Х,Х2..Хк => w,w2…wk = w
G G Г,
На первом шаге применяется продукция А —> У, У2… }’,„, которая, как мы знаем, есть в G. Следующая группа шагов представляет порождение е из тех У,, которые не являются ни одним из Xh Последняя группа шагов представляет порождения w, из X,, которые существуют по предположению индукции.
(Достаточность) Пусть А w и w Ф е. Докажем индукцией по длине п порождения,
G
*
что Л => w.
С,
Базис. Один шаг. А —> w является продукцией в G. Поскольку w Ф е, эта же продукция
есть и в Gh поэтому А => w.
а,
Индукция. Пусть в порождении п шагов, п> 1. Тогда оно имеет вид * *
А YiY2…Ym => w. Цепочку w можно разбить на wiw2…wk так, что Г, => w, для /’ = 1, 2,
G G G
…, т. Пусть Xh Х2, …, Хк будут теми из Yj (в порядке записи), для которых и», Ф е. к > 1, поскольку w Ф е. Таким образом, А —^Х,Х2…Хк является продукцией в G/.
Утверждаем, что Х,Х2..Х’к => w, поскольку только Yj, которых нет среди Х;, Х2, …, Хк,
G
использованы для порождения е и не вносят ничего в порождение w. Так как каждое из порождений Yj => wt содержит менее п шагов, к ним можно применить предположение ин-
G
* *
дукции и заключить, что если vi’; Ф е, то У, ==> wr Таким образом, А => Х,Х2.. ,Хк => w.
О | G[
Завершим доказательство. Нам известно, что w е L(Gj) тогда и только тогда, когда
S=>w. Полагая, что А = S в описанных выше рассуждениях, получаем, что w е L(G,) то-
*
гда и только тогда, когда S => w и w Ф е. Таким образом, w е L(Gi) тогда и только тогда,
G
когда w е L(G/) и w Ф е. □
7.1.4. Удаление цепных продукций
Цепная продукция — это продукция вида А —» В, где и А, и В являются переменными. Эти продукции могут быть полезными: в примере 5.27 мы видели, как использование цепных продукций Е—> Та Т—> F позволило построить следующую однозначную грамматику для простых арифметических выражений.
I а | Ъ 11а | lb 110 | Л
F Ц(Е) Т F| Г* F
Е Т\Е+Т
Вместе с тем, цепные продукции могут усложнять некоторые доказательства и создавать излишние шаги в порождениях, которые по техническим соображениям там совсем не нужны. Например, в продукции Е —> Т переменную Т можно расширить обоими возможными способами, заменив эту продукцию двумя: Е—»F| Т* F. Это изменение все еще не избавляет от цепных продукций из-за появления E—>F. Дальнейшая замена F да- ет Е —> 11 (Е) | Т * F, однако при этом остается Е —> I. Но если в этой продукции заменить / всеми шестью возможными способами, то получим следующие продукции.
£-> а | b | la | lb \ 10 \ 11 \ (E)\ T* F Как видно, цепных продукций для Е нет. Заметим, что продукция Е а не является цепной, единственный символ в ее теле — терминал, а не переменная.
Представленная выше техника расширения цепных продукций до их исчезновения работает довольно часто. Однако она терпит неудачу, если в грамматике есть цикл из цепных продукций, вроде АВ, В->С и С->А. Техника, гарантирующая результат,
включает первоначальное нахождение всех пар переменных А а В, для которых А => В получается с использованием последовательности лишь цепных продукций. Заметим, что
А => В возможно и без использования цепных продукций, например, с помощью продукций А —> ВС и С —> е.
Определив все подобные пары, любую последовательность шагов порождения, в которой А => В: => В2 => … => Вп => а с нецепной продукцией В„ —> а, можно заменить продукцией А —> а. Однако вначале рассмотрим индуктивное построение пар (А, В), для
которых А => В получается с использованием лишь цепных продукций. Назовем такую пару цепной парой (unit pair).
Базис. (А, А) является цепной парой для любой переменной, т.е. А => А за нуль шагов.
Индукция. Предположим, что пара (А, В) определена как цепная, и В —> С — продукция с переменной С. Тогда (А, С) — цепная пара.
Пример 7.10. Рассмотрим грамматику выражений из примера 5.27, воспроизведенную выше. Базис дает цепные пары (Е, Е), (Т, Т), (F, F) и (/, Г). На индуктивном шаге можно сделать следующие порождения пар.
(Е, Е) и продукция Е—>Тдают пару (Е, 7).
(Е, Г) и продукция T—>F — пару (Е, F).
(£, F) и F —> / дают пару (£, Г).
(Т, 7) и Г-» F— пару (£,/).
(Т, F) н F I — пару (Т, Г).
(F, F) и F —> / — пару (F, /).
Больше пар, которые можно было бы вывести, нет. На самом деле эти десять пар представляют все порождения, использующие только цепные продукции. □
Способ построения пар теперь очевиден. Нетрудно доказать, что предложенный алгоритм обеспечивает порождение всех нужных пар. Зная эти пары, можно удалить цепные продукции из грамматики и показать эквивалентность исходной и полученной грамматик.
Теорема 7.11. Приведенный выше алгоритм находит все цепные пары грамматики G, и только их.
Доказательство. С помощью индукции по порядку обнаружения пар нетрудно показать, что если пара (А, В) обнаружена, то А => В получается с использованием лишь
G
цепных продукций. Это оставляется в качестве упражнения.
Предположим, что А => В получено с использованием лишь цепных продукций. По-
G
кажем с помощью индукции по длине порождения, что пара (А, В) будет обнаружена.
Базис. Нуль шагов. Тогда А = В, и пара (А, В) обнаруживается согласно базису.
*
Индукция. Предположим, что А => В получено за п шагов, п > 0, и на каждом из них
G
применялась цепная продукция. Тогда порождение имеет вид А => С => В. Порождение
G
*
А => С состоит из п — 1 шагов, и по предположению индукции пара (А, С) обнаружива-
G
ется. Наконец, используем индуктивную часть алгоритма, чтобы по паре (А, С) и продукции С —> В обеспечить обнаружение пары (А, В). □
Для удаления цепных продукций по КС-грамматике G~(V,T,P,S) построим КС- грамматику G/ = (V/, T,PhS) следующим образом.
Найдем все цепные пары грамматики G.
Для каждой пары (А, В) добавим к Pi все продукции А а, где В —> а— нецепная продукция из Р. Заметим, что при А = В все нецепные продукции для В из Р просто добавляются к Р,.
Пример 7.12. Продолжим пример 7.10, где был выполнен шаг 1 описанного построения для грамматики выражений из примера 5.27. На рис. 7.1 представлен шаг 2 алгоритма, строящий новое множество продукций. При этом первый член пары становится головой продукций, а в качестве их тел используются все тела нецепных продукций для второго члена.
На заключительном шаге из грамматики (см. рис. 7.1) удаляются все цепные продукции. В итоге получается следующая грамматика без цепных продукций, которая порождает то же самое множество выражений, что и грамматика, изображенная на рис. 5.19.
Е Е + Т\Т* F | (£) | a j b | la | lb | /0 | Л Г —» Г * F | (£) \a\b\Ia\Ib\I0\l\ F->(E)\a\b\Ia\Ib\I0\Il I а \ b \ la \ lb \ 10 \ 1\
□
Теорема 7.13. Если грамматика G; построена по грамматике G с помощью алгоритма удаления цепных продукций, описанного выше, то L(G/) = 1(G).
Пара | Продукции | |||
(Е,Е) | Е^Е+Т | |||
(Е,Т) | E—>T*F | |||
СE,F) | ||||
(£,/) | Е —> a \b \ 1а | lb | I/O | 1/1 |
(Т,Г) | Т-> Т* F | |||
сT,F) | Г->(£) | |||
Ст,1) | Т^а\Ь\1а | lb | 10 | /1 |
(F,F) | F-*{E) | |||
(F,I) | F^a\b\ la | lb | I/O | 1/1 |
(А Г) | I—>a\b\Ia\ | lb 1 | 10 1 | /1 |
Рис. 7.1. Грамматика, построенная на шаге 2 алгоритма удаления цепных продукций Доказательство. Докажем, что w е L(G,) тогда и только тогда, когда w е 1(G). |
(Достаточность) Предположим, S => w. Поскольку каждая продукция фамматики
Gi
G, эквивалентна последовательности из нуля или нескольких цепных продукций G, за которой следует нецепная продукция G, из а (3 следует а => (3. Таким образом, каж-
Gx G
дый шаг порождения в G, может быть заменен одним или несколькими шагами в G. Собрав эти последовательности шагов вместе, получим, что S => w.
G
(,Необходимость) Предположим, что w е 1(G). Тогда в соответствии с эквивалент- ностями из раздела 5.2 цепочка w имеет левое порождение, т.е. S => w. Где бы в левом
1т
порождении ни использовалась цепная продукция, переменная ее тела становится крайней слева в выводимой цепочке и сразу же заменяется. Таким образом, левое порождение в G можно разбить на последовательность «шагов», в которых нуль или несколько цепных продукций сопровождаются нецепной. Заметим, что любая нецепная продукция, перед которой нет цепных, сама по себе образует такой «шаг». Но по построению грамматики G/ каждый из этих шагов может быть выполнен одной ее продукцией. Таким образом, S => w. □
Gi
Подведем итог различным упрощениям грамматик, описанным выше. Нам желательно преобразовывать любую КС-грамматику в эквивалентную, которая не имеет бесполезных символов, е-продукций и цепных продукций. При этом немаловажен порядок применения преобразований. Безопасным является следующий.
Удалить е-продукции.
Удалить цепные продукции.
Удалить бесполезные символы.
Заметим, что подобно тому, как в разделе 7.1.1 результат удаления бесполезных символов зависел от порядка соответствующих шагов, данные три шага должны быть упорядочены именно так, иначе в грамматике могут остаться удаляемые элементы.
Теорема 7.14. Если G— КС-грамматика, порождающая язык, в котором есть хотя бы одна непустая цепочка, то существует другая грамматика G/, не имеющая бесполезных символов, е-продукций и цепных продукций, у которой L(G/) = 1(G) — {£}.
Доказательство. Начнем с удаления е-продукций методом, описанным в разделе 7.1.3. Если затем удалить цепные продукции (см. раздел 7.1.4), то е-продукции не появятся, поскольку каждое из тел новых продукций совпадает с некоторым телом одной из старых. Наконец, удалим бесполезные символы методом раздела 7.1.1. Поскольку это преобразование только удаляет продукции и символы, не вводя новых, то получаемая грамматика будет по-прежнему свободна от цепных и е-продукций. □
7.1.5. Нормальная форма Хомского
Завершим изучение грамматических упрощений, показав, что для каждого непустого КС-языка, не включающего е, существует грамматика G, все продукции которой имеют одну из следующих двух форм.
А —> ВС, где А, В а С — переменные.
А —> а, где А — переменная, а — терминал.
Кроме того, G не имеет бесполезных символов. Такая форма грамматик называется нормальной формой Хомского, или НФХ, а грамматики в такой форме — НФХ-грамматиками.
Для приведения грамматики к НФХ начнем с ее формы, удовлетворяющей теореме 7.14, т.е. грамматика свободна от бесполезных символов, цепных и е-продукций. Каждая продукция такой грамматики либо имеет вид А —> а, допустимый НФХ, либо имеет тело длиной не менее 2. Нужно выполнить следующие преобразования:
а) устроить так, чтобы все тела длины 2 и более состояли только из переменных;
б) разбить тела длины 3 и более на группу продукций, тело каждой из которых состоит из двух переменных.
Конструкция для а следующая. Для каждого терминала а, встречающегося в продукции длины 2 и более, создаем новую переменную, скажем, А. Эта переменная имеет единственную продукцию А —> а. Используем переменную А вместо а везде в телах продукций длины 2 и более. Теперь в теле каждой продукции либо одиночный терминал, либо как минимум две переменные и нет терминалов.
Для шага б нужно разбить каждую продукцию вида А —> В,В2…Вк, где к > 3, на группу продукций с двумя переменными в каждом теле. Введем к- 2 новых переменных С/, С;,…, и заменим исходную продукцию на к-1 следующих продукций.
—» fi/С/, С/ —> брСр, ■.., C’k j —> 2Q. 2, Сь 2 Вк /Вк
Пример 7.15. Приведем грамматику из примера 7.12 к НФХ. Для части а заметим, что у грамматики есть восемь терминалов, я, Ь, 0, 1 ,+,*,( и ), каждый из которых встречается в теле, не являющемся одиночным терминалом. Таким образом, нужно ввести восемь новых переменных, соответствующих этим терминалам, и восемь следующих продукций, где переменная заменяется «своим» терминалом.
А^а В^Ъ Z-> О 0-> 1 М->* L->( /?->) Введя эти продукции и заменив каждый терминал в теле, не являющемся одиночным терминалом, соответствующей переменной, получим грамматику, изображенную на рис. 7.2.
Е —> ЕРТ | TMF | LER \a\b\lA\lB\IZ\10 ТTMF | LER\a\b\IA\IB\IZ\IO F—»LER \a\b\IA\IB\IZ\IO I а \ b \ IA \ IB \ IZ \ Ю А^а В^Ь Z^O 0-> 1 />-» + л/->* I-K Л->)
Рис. 7.2. Преобразование тел к одиночным терминалам или нескольким переменным
Теперь все продукции находятся в НФХ, за исключением тех, тела которых имеют длину 3: ЕРТ, TMF, LER. Некоторые из этих тел встречаются в нескольких продукциях, но каждое тело преобразуется один раз.
Для тела ЕРТ вводится новая переменная С/, и продукция Е —> ЕРТ меняется на £-» £С/ и С/ —> РГ. Для тела TMF вводится переменная С2. Две продукции с этим телом, £-4 TMF и 7’—> TMF,’меняются на Е 7’С2, ГС2 и С2 MF. Для ££/? вводится С5 и три продукции с этим телом, Е —> LER, Т —> и L£/?, меняются на Е —> T-)LC3,F-^LC3 и Q —> £/?. Окончательная НФХ-фамматика показана на рис. 7.3.
E-*EC,\TC2\LC3\a\b\IA\IB\IZ\Ю
T —» TC21 LC3 \a\b\IA\IB\IZ\IO
F —» LC3 \ a\b \ IA \ IB\ IZ\IO
I a\b\ IA \ IB \ IZ\ IO
A —> a
B->b
Z->0
1 *
£->( л-О
С, ->РГ C2->MF C3->ER
Рис. 7.3. Преобразование тел к одиночным терминалам или двум переменным
Теорема 7.16. Если G— КС-грамматика, язык которой содержит хотя бы одну непустую цепочку, то существует НФХ-грамматика G/, причем L(G,) = L(G) — {е}.
Доказательство. По теореме 7.14 можно найти КС-грамматику G2, для которой L(G2) = L(G) — {е}, причем G2 свободна от бесполезных символов, цепных и е-продукций. Конструкция, преобразующая G2 в НФХ
-грамматику О/, изменяет продукции таким образом, что каждая продукция из G2 может быть проимитирована одной или несколькими продукциями из Gj. Наоборот, каждая из введенных в G, переменных соответствует лишь одной продукции, поэтому эти переменные можно использовать только надлежащим образом. Более строго, докажем, что w е L(G2) тогда и только тогда, когда w е ЦС,).
(Необходимость) Если w порождается в G2, то легко заменить каждую использованную продукцию, скажем, А —^XtX2…Xk, последовательностью продукций из G/. Таким образом, один шаг порождения в G2 превращается в один или несколько шагов в порождении w, использующем продукции G,. Во-первых, если X,— терминал, то G; имеет соответствующую переменную В, и продукцию В, —> X,. Во-вторых, если к > 2, то G/ имеет продукции А —> BtCh Ci —> В2С2 и так далее, где В/ есть либо переменная, введенная для терминала Xh либо сам Х„ если это переменная. Эти продукции имитируют в G/ один шаг порождения в G2, использующий продукцию А —^Х1Х2…Хк. Делаем вывод, что в G, существует порождение w, поэтому w е L(G,).
(Достаточность) -Предположим, что w е L(Gi). Тогда в G/ существует дерево разбора с отметкой корня S и кроной w. Преобразуем это дерево в дерево разбора в G2, также имеющее отметку корня S и крону w.
Сначала «сделаем откат» части б построения НФХ. Предположим, существует узел с отметкой А и сыновьями, отмеченными В, и С/, где С/ — одна из переменных, введенных в части 6. Тогда данная часть дерева разбора должна выглядеть, как на рис. 7.4, а. Поскольку каждая из этих введенных переменных соответствует лишь одной продукции, существует только один способ для их возникновения, и все эти переменные, предназначенные для обработки продукции А —> BjB2.. .Вк, должны появляться вместе (см. рис. 7.4, а).
Каждый такой куст узлов в дереве разбора можно заменить продукцией, которую они представляют. Преобразование дерева разбора показано на рис. 7.4, б.
Полученное дерево все еще не обязательно является деревом разбора в G2. Причина в том, что на шаге а построения НФХ были введены другие переменные, порождающие
б)
Рис. 7.4. Дерево разбора должно использовать введенные переменные специальным образом |
одиночные терминалы. Однако их можно обнаружить в полученном дереве разбора и заменить узел, отмеченный такой переменной А, и его единственного сына, отмеченного а, одиночным узлом с отметкой а. Теперь каждый внутренний узел дерева разбора образует продукцию G2, и мы приходим к выводу, что w е ЦС72). □
Нормальная форма Грейбах
Существует еще одна интересная нормальная форма для грамматик, которая не будет обоснована. Любой непустой язык, не включающий е, есть L(G) для некоторой грамматики G с продукциями вида А —> аа, где а — терминал, а а— цепочка из нуля или нескольких переменных. Преобразование грамматики к этой форме является сложным, даже если задачу упростить, скажем, начав с НФХ-грамматики. Иначе говоря, первая переменная каждой продукции расширяется до тех пор, пока не будет получен терминал. Однако на этом пути возможны циклы, в которых терминал не достигается, и этот процесс необходимо «замкнуть». Для того чтобы породить все последовательности переменных, которые могут появиться на пути к порождению этого терминала, создается продукция с терминалом в качестве первого символа тела и переменными вслед за ним.
Эта форма, называемая нормальной формой Грейбах, по имени Шейлы Грейбах (Sheila Greibach), которая первой дала способ построения таких грамматик, имеет несколько интересных следствий. Поскольку каждое использование продукции вводит ровно один терминал в выводимую цепочку, цепочка длины п порождается в точности за п шагов. Кроме того, если применить конструкцию из теоремы 6.13 для построения МП-автомата по грамматике в нормальной форме Грейбах, то получается МП-автомат без е-переходов, показывающий, что такие переходы в МП-автомате всегда можно удалить.
7.1.6. Упражнения к разделу 7.1
(*) Найдите грамматику, не содержащую бесполезных символов и эквивалентную следующей грамматике.
S АВ \ СА А а В-^ВС\АВ С аВ\Ь
Рассмотрите следующую грамматику: S ASB|е
А aAS \ а В —> SbS \A\bb а) удалите е-продукции;
б) удалите цепные продукции;
в) есть ли здесь бесполезные символы? Если да, удалите их;
г) приведите грамматику к нормальной форме Хомского.
Выполните упражнение 7.1.2 со следующей грамматикой.
S-*0A0 | 1В1 | ВВ Л —»С B—>Sj Л С—>51 е
Выполните упражнение 7.1.2 со следующей грамматикой.
S^AAA\B А аА j В
Выполните упражнение 7.1.2 со следующей грамматикой.
S—» аАа | ЬВЬ \ е А—>С\а
С —» CDE|е
Постройте НФХ-грамматику для множества цепочек сбалансированных скобок. Можно начать с грамматики, находящейся в НФХ.
(!!) Пусть G — КС-грамматика с р продукциями и длины тел продукций не превосходят п. Докажите, что если А => е, то найдется порождение £ из А, в кото-
G
ром не более, чем (ир — 1)/(п — 1) шагов. Как близко можно на самом деле подойти к этой границе?
(!) Предположим, что нам дана грамматика Gen продукциями, ни одна из которых не является £-продукцией, и мы преобразуем ее в НФХ:
а) докажите, что НФХ-грамматика имеет не более, чем 0(п2) продукций;
б) докажите, что у НФХ-грамматики число продукций может быть прямо пропорциональным п2. Указание. Рассмотрите конструкцию удаления цепных продукций.
Дайте индуктивные доказательства, необходимые для завершения следующих теорем:
а) часть теоремы 7.4, в которой доказывалось, что обнаруживаемые символы действительно являются порождающими;
б) теорема 7.6 в обе стороны, где доказывалась корректность алгоритма из раздела 7.1.2 для обнаружения достижимых символов;
в) часть теоремы 7.11, где доказывалось, что все обнаруженные пары действительно являются цепными парами.
(*!) Можно ли для каждого КС-языка найти грамматику, все продукции которой имеют вид или А —» BCD (тело состоит из трех переменных), или А а (тело образовано одиночным терминалом)? Приведите либо доказательство, либо контрпример.
В этом упражнении показывается, что для каждого КС-языка L, содержащего хотя бы одну непустую цепочку, найдется КС-грамматика в нормальной форме Грейбах, порождающая L — {е}. Напомним, что тела продукций грамматики в нормальной форме Грейбах (НФГ) начинаются терминалом. В построении используется ряд лемм и конструкций.
Пусть КС-грамматика G имеет продукцию А —> аВ(3, и всеми продукциями для В являются В —» у/1 у21 … | у„. Заменив А —> осВ/З всеми продукциями, у которых вместо В подставлены тела всех б-продукций, получим А —> осуф\ ауф1 … | ау„Д Построенная грамматика порождает тот же язык, что и G.
Далее будем предполагать, что грамматика G для L находится в нормальной форме Хомского, а ее переменные обозначены Ah А2, …, Ак.
(*!) Докажите, что путем повторных применений преобразования из части 1 грамматику G можно превратить в эквивалентную грамматику, у которой тело каждой продукции для А, начинается или терминалом, или At для некоторого j > i. В обоих случаях все символы после первого в теле продукции — переменные.
(!) Пусть G/— грамматика, полученная из G путем выполнения шага 2. Пусть А,— произвольная переменная и А, —» А,а,\ … | А,ат— все А,- продукции, тело которых начинается с А,. Пусть А, —» Д1 … | Д,— все остальные Aj-продукции. Заметим, что каждое Д начинается либо терминалом, либо переменной с индексом больше /. Введем новую переменную В/ и заменим первую группу из т продукций следующими:
-^РЛ-ЛРп
а/В, I а, I … I атВ, | ат
Докажите, что полученная грамматика порождает тот же язык, что и G или G,.
(*!) Пусть после шага 3 получена грамматика G2. Отметим, что тела всех А,- продукций начинаются или терминалом, или Aj с j > i. Кроме того, тела В,- продукций начинаются или терминалом, или некоторым Aj. Докажите, что G2 имеет эквивалентную грамматику в НФГ. Указание. Сначала преобразуй-
те должным образом продукции для Ак, затем для ; и так далее до A h используя часть 1. Затем снова с помощью части 1 преобразуйте продукции для В, в любом порядке. 7.1.12. Используйте построения из упражнения 7.1.11 для преобразования в НФГ следующей грамматики.
S-+AA |0 А SS | 1
7.2. Лемма о накачке для контекстно-свободных языков
В этом разделе развивается инструмент доказательства, что некоторые языки не являются контекстно-свободными. Теорема, называемая «леммой о накачке для контекстно-свободных языков»[1], гласит, что в любой достаточно длинной цепочке КС-языка можно найти две близлежащие короткие подцепочки (одна из них может быть пустой) и совместно их «накачивать». Таким образом, обе подцепочки можно повторить / раз для любого целого /, и полученная цепочка также будет принадлежать языку.
Эта теорема отличается от аналогичной для регулярных языков (теорема 4.1), гласящей, что всегда можно найти одну короткую цепочку для ее накачки. Разница видна, если рассмотреть язык типа L= {0″ln | и > 1}. Можно показать, что он нерегулярен, если зафиксировать п и накачать подцепочку из нулей, получив цепочку, в которой символов О больше, чем 1. Однако лемма о накачке для КС-языков утверждает, что можно найти две короткие цепочки, поэтому нам пришлось бы использовать для накачки цепочку из нулей и цепочку из единиц, порождая таким образом только цепочки из L. Этот результат нас устраивает, так как L — КС-язык, а для построения цепочек, не принадлежащих языку L, лемма о накачке для КС-языков использоваться и не должна.
7.2.1. Размер деревьев разбора
Первый шаг на пути к лемме о накачке для КС-языков состоит в том, чтобы рассмотреть вид и размер деревьев разбора. Одно из применений НФХ — преобразовывать деревья разбора в бинарные (двоичные). Такие деревья имеют ряд удобных свойств, и одно из них используется здесь.
Теорема 7.17. Пусть дано дерево разбора, соответствующее НФХ-грамматике G= (V, Т, Р, S), и пусть кроной дерева является терминальная цепочка w. Если п — наибольшая длина пути (от корня к листьям), то |w| < 2″ 1.
Доказательство. Докажем с помощью простой индукции по п.
Базис. и= 1. Напомним, что длина пути есть число ребер, т.е. на 1 меньше числа узлов. Таким образом, дерево с максимальной длиной пути 1 состоит из корня и листа, отмеченного терминалом. Цепочка w является этим терминалом, и |w| = 1. Поскольку = 2° = 1, базис доказан.
Индукция. Предположим, самый длинный путь имеет длину п, и п> 1. Корень де-‘ рева использует продукцию, которая должна иметь вид А —> ВС, поскольку п > 1, т.е. нельзя начать дерево, использовав продукцию с терминалом. Ни один из путей в поддеревьях с корнями в В и С не может иметь длину больше, чем п— 1, так как в этих путях исключено ребро от корня к сыну, отмеченному В или С. Таким образом, по предположению индукции эти два поддерева имеют кроны длины не более 2″~2. Крона всего дерева представляет собой конкатенацию этих двух крон, поэтому имеет длину не более 2П~2 + 2″~2 = 2″~2. Шаг индукции доказан. □
7.2.2. Утверждение леммы о накачке
Лемма о накачке для КС-языков подобна лемме о накачке для регулярных языков, но каждая цепочка z КС-языка L разбивается на пять частей, и совместно накачиваются вторая и четвертая из них.
Теорема 7.18. (Лемма о накачке для КС-языков.) Пусть L — КС-язык. Тогда существует такая константа п, что если z— произвольная цепочка из L, длина которой не меньше п, то можно записать z = uvwxy, причем выполняются следующие условия.
\vwx\ < п. Таким образом, средняя часть не слишком длинная.
vx Ф е. Поскольку v и х — подцепочки, которые должны «накачиваться», это условие гласит, что хотя бы одна из них непуста.
uv’wx’y е L для всех i > 0. Две цепочки, v и х, могут быть «накачаны» произвольное число раз, включая 0, и полученная при этом цепочка также будет принадлежать L.
Доказательство. Вначале для L найдем грамматику G в нормальной форме Хомского. Технически это невозможно, если L есть КС-язык 0 или {£}. Однако при L = 0 утверждение теоремы, которое говорит о цепочке z, не может быть нарушено, поскольку такой цепочки z нет в 0. НФХ-грамматика G в действительности порождает L- {£}, но это также не имеет значения, поскольку выбирается п > 0, и z никак не сможет быть £.
Итак, пусть НФХ-грамматика G = (V, T,P,S) имеет т переменных и порождает язык L(G)= L~ {£}. Выберем п = 2™. Предположим, что z из L имеет длину не менее п. По теореме 7.17 любое дерево разбора, наибольшая длина путей в котором не превышает т, должно иметь крону длиной не более 2т~1 = и/2. Такое дерево разбора не может иметь крону z, так как z для этого слишком длинная. Таким образом, любое дерево разбора с кроной z имеет путь длиной не менее т + 1.
На рис. 7.5 представлен самый длинный путь в дереве для z, где к не менее т, и путь имеет длину к + 1. Поскольку к > т, на этом пути встречается не менее т + 1 переменных Ао, А/, …, Ак. Но V содержит всего т различных переменных, поэтому хотя бы две из т+ 1 последних переменных на пути (т.е. от т до А* включительно) должны совпадать. Пусть Л,- = Ар где к- т< i <] < к.
Тогда дерево можно разделить так, как показано на рис. 7.6. Цепочка w является кроной поддерева с корнем Aj. Цепочки v и х — это цепочки соответственно слева и справа от w в кроне большего поддерева с корнем А/. Заметим, что цепных продукций нет, поэтому v и х не могут одновременно быть е, хотя одна из них и может. Наконец, и и у образуют части z, лежащие соответственно слева и справа от поддерева с корнем А,.
Рис. 7.5. Каждая достаточно длинная цепочка в L должна иметь длинный путь в своем дереве разбора |
Если Л, = Aj = А, то по исходному дереву можно построить новое дерево разбора, как показано на рис. 7.7, а. Сначала можно заменить поддерево с корнем А,-, имеющее крону vwx, поддеревом с корнем А„ у которого крона w. Это допустимо, поскольку корни обоих поддеревьев отмечены одной и той же переменной А. Полученное дерево представлено на рис. 7.7, б. Оно имеет крону и соответствует случаю / = 0 в шаблоне цепочек uv’wx’y.
Еще одна возможность представлена на рис. 7.7, в. Там поддерево с корнем Aj заменено поддеревом с корнем А,. Допустимость этой замены также обусловлена тем, что отметки корней совпадают. Кроной этого дерева является uvzwx2y. Если бы мы затем заменили поддерево с кроной w (см. рис. 7.7, в) большим поддеревом с кроной vwx, то получили бы дерево с кроной uviwx2‘y и так далее для любого показателя i. Итак, в G существуют деревья разбора для всех цепочек вида uv’wx’y, и лемма о накачке почти доказана.
Осталось условие 1, гласящее, что \vwx\ < п. Мы выбирали А, как можно ближе к кроне дерева, поэтому k — i<m. Таким образом, самый длинный путь в поддереве с корнем
S
———————— z ► Рис. 7.6. Разделение цепочки z для накачивания |
7.2.3. Приложения леллллы о накачке к КС-языкам
Отметим, что лемма о накачке для КС-языков, как и для регулярных языков, используется в виде «игры с противником» следующим образом.
Мы выбираем язык L, желая доказать, что он не контекстно-свободный.
Наш «противник» выбирает заранее неизвестное нам п, поэтому мы должны рассчитывать на любое возможное значение.
Мы выбираем z и при этом можем использовать п как параметр.
Противник разбивает z на uvwxy, соблюдая ограничения |vwx| < п и vx * е.
Мы «выигрываем», если можем, выбирая i и показывая, что uvwx’y не принадлежит языку L.
Рассмотрим несколько примеров языков, о которых с помощью леммы о накачке можно доказать, что они не контекстно-свободные. Первый пример показывает, что хотя цепочки контекстно-свободных языков могут иметь по две соответствующие друг другу группы символов, но три такие группы уже невозможны.
Aj имеет длину не более т + 1. По теореме 7.17 поддерево с корнем At имеет крону, длина которой не больше, чем 2™ = п. □ |
Пример 7.19. Пусть L = {0″Г2П | п > 1}, т.е. L состоит из цепочек вида 0+1+2+ с одинаковыми количествами каждого из символов, например, 012, 001122 и т.д. Предполо
жим, что L контекстно-свободный. Тогда существует целое п из леммы о накачке.[2] Выберем 0″ 1 «2».
Рис. 7.7. Накачивание цепочек v их 0 раз и 2 раза |
Предположим, что «противник» разбивает z как г = uvwxy, где |vwx| < п и v и х не равны е одновременно. Тогда нам известно, что vwx не может включать одновременно нули и двойки, поскольку последний нуль и первая двойка разделены п + 1 позициями. Докажем, что L содержит некоторую цепочку, которая не может быть в L, получив тем самым противоречие к предположению, что L контекстно-свободный. Возможны следующие случаи.
- vwx не имеет двоек, т.е.vx состоит только из нулей и единиц и содержит хотя бы один из этих символов. Тогда цепочкаuwy, которая по лемме о накачке должна быть в L, имеет п двоек, но меньше, чем п нулей или единиц. Следовательно, она не принадлежит L, и в этом случае L не контекстно-свободен.
- vwx не имеет нулей. Аналогично,uwy имеет п нулей, но меньше двоек или единиц,
поэтому не принадлежит L. В любом случае приходим к выводу, что L содержит цепочку, которая не может ему принадлежать. Это противоречие позволяет заключить, что наше предположение ложно, т.е. L не является КС-языком. □
Еще одно свойство КС-языков состоит в том, что в их цепочках не может быть двух соответствующих друг другу перемежающихся пар равных количеств символов. Эта идея уточняется следующим примером.
Пример 7.20. Пусть L = {0’lj2’3j | i > 1 и у > 1}. Если он контекстно-свободен, то пусть п — константа для L, и выберем г = 0nln2n3″. Можно записать z = uvwxy, соблюдая обычные ограничения \vwx\ < п и vx Ф г. Тогда vwx или состоит из символов одного вида, или захватывает символы двух различных соседних видов.
Если vwx состоит из символов одного вида, то uwy имеет по п символов трех различных видов и меньше, чем п символов четвертого вида. Таким образом, uwy не может быть в L. Если vwx захватывает символы двух различных соседних видов, скажем, единицы и двойки, то в uwy их не хватает. Если не хватает единиц, то, поскольку там есть п троек, эта цепочка не может быть в L. Если же не хватает двоек, то uwy также не может быть в L, поскольку содержит п нулей. Получаем противоречие к предположению о том, что L — КС-язык, и приходим к выводу, что он таковым не является. □
В заключительном примере покажем, что в цепочках КС-языков не может быть двух одинаковых цепочек произвольной длины, если они выбираются в алфавите, состоящем более чем из одного символа. Следствием этого замечания, между прочим, является то, что КС-грамматики не являются подходящим механизмом для описания определенных «семантических» ограничений в языках программирования, например, что идентификатор должен быть объявлен до его использования. На практике для запоминания объявленных идентификаторов используется другой механизм, «таблица символов», и никто не пытается строить синтаксический анализатор, который проверял бы соблюдение принципа «определение до использования».
Пример 7.21. Пусть L — {ww | we {0, 1 }*}, т.е. L состоит из повторяющихся цепочек, например, е, 0101, 00100010 или 110110. Если он контекстно-свободный, то пусть п— константа из леммы о накачке для L. Рассмотрим цепочку z = 0nln0nln. Очевидно, z е L.
Следуя шаблону предыдущих примеров, можно записать z = uvwxy, причем |vwx| < п и vx Ф е. Покажем, что uwy не принадлежит L, тем самым доказав от противного, что L не может быть КС-языком.
Заметим сразу, что, поскольку |vwx| < п, то \uwy\ > Ъп. Таким образом, если uwy является повторением цепочки, скажем, tt, то t имеет длину не менее Зи/2. Возможны несколько вариантов в зависимости от расположения vwx в пределах z.
Предположим, vwx находится в пределах первых п нулей. Для определенности пусть vx состоит из к нулей, где к>0. Тогда uwy начинается с 0″~к1п. Поскольку \uwy\ = 4п-к и по предположению uwy = tt, то = 2п — к/2. Таким образом, t не заканчивается в первом блоке из единиц, т.е. заканчивается символом 0. Но uwy заканчивается единицей, поэтому не может равняться tt.
Предположим, vwx захватывает первый блок нулей и первый блок единиц. Возможно, vx состоит только из нулей, если х = е. Тогда uwy не может быть вида tt по той же причине, что и в случае 1. Если же vx содержит хотя бы одну единицу, то t, длина которой не менее Зп/2, должна заканчиваться на 1″, поскольку uwy заканчивается на 1″. Однако из п единиц состоит только последний блок в uwy, поэтому t не может повторяться в uwy.
Если vwx содержится в первом блоке единиц, то uwy не может быть в L по тем же причинам, что и во второй части случая 2.
Предположим, vwx захватывает первый блок единиц и второй блок нулей. Если vx не имеет нулей, то все получается так же, как если бы vwx содержалась в первом блоке единиц. Если vx содержит хотя бы один нуль, то uwy начинается блоком из п нулей, как и t, если uwy = tt. Однако в uwy второго блока из п нулей для t нет, поэтому uwy не может быть в L.
В остальных случаях, когда vwx находится во второй части z, аргументы симметричны по отношению к случаям, когда vwx содержится в первой части z.
Итак, в любом случае uwy не принадлежит L, и мы приходим к выводу, что L не контекстно-свободный.
7.2.4. Упражнения к разделу 7.2
7.2.1. Используйте лемму о накачке для КС-языков, чтобы показать, что каждый из
следующих языков не контекстно-свободный.
а) (*) {dVck\i<j <к}-,
б) {anbnc’\i<n}-,
в) {0р|/>— простое}. Указание. Используйте те же идеи, что и в примере 4.3, где доказывалась нерегулярность этого языка;
г) (*!){0’1 j|y = /2};
д) (!) {a»Z>V|rc</<2rc};
е) (!) {vfvfRvf | w— цепочка из нулей и единиц}, т.е. множество цепочек, состоящих из цепочки w, за которой записаны ее обращение и она же еще раз, например 001100001.
- (!) Когда мы пытаемся применить лемму о накачке к КС-языку, «выигрывает противник», и нам не удается завершить доказательство. Покажите, что является ошибочным, когда в качестве L выбирается один из следующих языков:
а) {00,11};
б) (*) {0ПГ|«> 1};
в) (*) множество палиндромов в алфавите {0, 1}.
- (!) Существует более сильная версия леммы о накачке для КС-языков, известная как лемма Огдена. Она отличается от доказанной леммы о накачке тем, что позволяет нам сосредоточиться на любых п «выделенных» позициях цепочки z и гарантирует, что накачиваемые цепочки содержат от 1 до п выделенных позиций. Преимущество этого свойства в том, что язык может иметь цепочки, состоящие из двух частей, одна из которых может быть накачана без создания цепочек, не принадлежащих языку, тогда как вторая при накачке обязательно порождает цепочки вне языка. Если мы не можем утверждать, что накачка имеет место во второй части, то мы не можем завершить доказательство того, что язык не контекстно-свободный. Формальное утверждение леммы Огдена состоит в следующем. Для любого КС-языка L существует такая константа п, что если z — произвольная цепочка из L длиной не менее п, в которой выделено не менее п различных позиций, то 2 можно записать в виде uvwxy, причем выполняются следующие условия.
- vwx имеет не более п выделенных позиций.
- vx имеет хотя бы одну выделенную позицию.
- uv’wx’y е L для всех i >
Докажите лемму Огдена. Указание. Доказательство на самом деле весьма похоже на доказательство леммы о накачке (теорема 7.18), если мы представим себе, что в том доказательстве невыделенные позиции цепочки 2 отсутствуют, когда выбирается длинный путь в дереве разбора для z.
- (*) Используйте лемму Огдена (упражнение 7.2.3) для упрощения доказательства того, что L = {ww | we {0, 1 }*} —не КС-язык (см. пример 7.21). Указание. В выбранной цепочке z сделайте выделенной только одну группу из п последовательных символов.
- Используйте лемму Огдена (упражнение 7.2.3) для доказательства того, что следующие языки не являются контекстно-свободными:
а) (!) {0’1-«0к \j = шах(/, к)};
б) (!!) {a»b»c \ i Ф п). Указание. Рассмотрите цепочку z = anbncn‘, где п— константа из леммы Огдена.
7.3. Свойства замкнутости контекстно-свободных языков
Рассмотрим некоторые операции над контекстно-свободными языками, которые гарантированно порождают КС-языки. Многие из этих свойств замкнутости соответствуют теоремам для регулярных языков из раздела 4.2. Однако есть и отличия.
Вначале введем операцию подстановки, по которой каждый символ в цепочках из одного языка заменяется целым языком. Эта операция обобщает гомоморфизм, рассмотренный в разделе 4.2.3, и является полезной в доказательстве свойств замкнутости КС- языков, относительно некоторых других операций, например, регулярных (объединение, конкатенация и замыкание). Покажем, что КС-языки замкнуты относительно гомоморфизма и обратного гомоморфизма. В отличие от регулярных языков, КС-языки не замкнуты относительно пересечения и разности. Однако пересечение или разность КС-языка и регулярного языка всегда является КС-языком.
7.3.1. Подстановки
Пусть 2 — алфавит. Предположим, для каждого символа а из 2 выбран язык La. Выбранные языки могут быть в любых алфавитах, не обязательно 2 и не обязательно одинаковых. Выбор языков определяет функцию s (подстановка, substitution) на 2, и La обозначается как s(a) для каждого символа а.
Если w = а,а2…а„— цепочка из 2*, то s(w) представляет собой язык всех цепочек xix2…x„, у которых для /’ = 1,2, …, п цепочка х, принадлежит языку s(a,). Иными словами, s(w) является конкатенацией языков s(ai)s(a2)…s(a„). Определение 5 можно распространить на языки: s(L) — это объединение s(w) по всем цепочкам w из L.
Пример 7.22. Пусть s(0) = {anbn \ п > 1} и s(l) = {аа, bb), т.е. 5 — подстановка на алфавите 2= {0, 1}. Язык i(0) представляет собой множество цепочек с одним или несколькими символами а, за которыми следует такое же количество b, а.?(1) — конечный язык, состоящий из двух цепочек аа и bb.
Пусть w = 01. Тогда s(vv) есть конкатенация языков .s(0).s(l). Точнее, s(w) состоит из всех цепочек вида <fbnaa и <?Ьп+г, где п > 1.
Теперь предположим, что L = 7.(0 ), т.е. множество всех цепочек из нулей. Тогда s(L) = (s(0))*. Этот язык представляет собой множество всех цепочек вида
a'»b'»a»>b’h …c^b'»
для некоторого k>0 и произвольной последовательности положительных целых п,, п2, …, щ. Он включает, например, цепочки £, aabbaaabbb и abaabbabab. □
Теорема 7.23. Если L — КС-язык в алфавите 2, а 5 — подстановка на 2, при которой i(a) является КС-языком для каждого а из 2, то s(L) также является КС-языком.
Доказательство. Основная идея состоит в том, что мы можем взять КС-грамматику для £ и заменить каждый терминал а стартовым символом грамматики для языка s(a). В результате получим единственную грамматику, порождающую s(L). Однако тут нужно быть аккуратным.
Более формально, пусть грамматика G = (V, X, Р, S) задает язык L, а грамматика Ga = (К, Та, Ра, Sa) — язык, подставляемый вместо каждого а из X. Поскольку для переменных можно выбирать любые имена, обеспечим, чтобы множества имен переменных V и Va (для всех а) не пересекались. Цель такого выбора имен — гарантировать, что при сборе продукций разных грамматик в одно множество невозможно случайно смешать продукции двух грамматик, и, таким образом, получить порождения, невозможные в данных грамматиках.
Построим новую грамматику G’~ (V, Т\ Р’, S) для s(L) следующим образом.
- V’ представляет собой объединение V и всех Va по а из X.
- Т’ является объединением Та по а из X.
- Р’ состоит из следующих продукций.
- Все продукции каждого из Ра для а из X.
- Все продукции Р, но с изменением везде в их телах каждого терминала а на Sa.
Таким образом, все деревья разбора в грамматике G’ начинаются как деревья разбора в G, но вместо того, чтобы порождать крону в X , они содержат границу, на которой все узлы отмечены переменными Sa вместо а из X. Каждый такой узел является корнем дерева в Ga, крона которого представляет собой терминальную цепочку из s(a) (рис. 7.8).
s
Рис. 7.8. Дерево разбора в G’ начинается деревом разбора в G и заканчивается многими деревьями, соответствующими грамматикам Ga |
Докажем, что описанная конструкция правильна в том смысле, что G’ порождает язык s(L). Формально будет доказано следующее утверждение.
- Цепочка w принадлежит L(G’) тогда и только тогда, когда w принадлежит s{L).
(Достаточность) Пусть w принадлежит s(L). Тогда существует цепочка х = а,а2…а„ в L и такие цепочких, в s(a,) при i= 1, 2, …, п, для которых vv = х,х2…х„. Тогда часть G’, образованная продукциями из G с подстановками Sa вместо каждого а, порождает цепочку, которая выглядит, как х, но с Sa вместо каждого а, т.е. цепочку Sa,Sa2…San. Эта часть порождения w представлена верхним треугольником на рис. 7.8.
Продукции каждой Ga являются также продукциями G’ поэтому порождение х, из Sa, есть также порождение в G’. Деревья разбора для этих порождений представлены на рис. 7.8 нижними треугольниками. Поскольку крона этого дерева разбора в G’ есть xix2…x„ = w, приходим к выводу, что w принадлежит L(G’).
(Необходимость) Предположим, что w принадлежит L(G’). Утверждаем, что дерево разбора для w должно выглядеть, как дерево на рис. 7.8. Причина в том, что переменные каждой из грамматик G и Ga для а из £ попарно различны. Таким образом, верхушка дерева, начинающаяся переменной S, должна использовать только продукции G до тех пор, пока не будет порожден некоторый символ Sa, а под этим символом могут использоваться только продукции грамматики Ga. В результате, если w имеет дерево разбора Т, можно выделить цепочку а1а2…а„ в L(G) и цепочки х, в языках s(a,), для которых верно следующее.
- и> = х/х2…х„.
- Цепочка SalSa2…Sa„ является кроной дерева, образованного из Г удалением некоторых поддеревьев (см. рис. 7.8).
Но цепочка xix2…x„ принадлежит s(L), поскольку образована подстановкой цепочек х, вместо каждого из а,. Таким образом, делаем вывод, что w принадлежит s(L). □
7.3.2. Приложения теоремы о подстановке
С использованием теоремы 7.23 можно обосновать несколько свойств замкнутости, хорошо знакомых нам по регулярным языкам. Перечислим их в следующей теореме.
Теорема 7.24. Контекстно-свободные языки замкнуты относительно следующих операций.
- Объединение.
- Конкатенация.
- Замыкание (*) и транзитивное замыкание (+).
- Гомоморфизм.
Доказательство. Каждое утверждение требует лишь определения соответствующей подстановки. Каждое из следующих доказательств использует подстановку контекстно- свободных языков в другие, в результате чего по теореме 7.23 порождаются КС-языки.
- Объединение. ПустьLi иL2— КС-языки. Тогда L,{J L2 является языком s(L), где L — язык {1, 2}, as — подстановка, определяемая как.s(l) = L, и s(2) = L2.
- Конкатенация. ПустьLt и L2 — КС-языки. Тогда LiL2 представляет собой язык s(L), где L — язык {12}, a s — такая же подстановка, как и в п. 1.
- Замыкание и транзитивное замыкание. ЕслиLj — КС-язык,L — язык {1 }*, a s — подстановка s(l) =Lh то L* = s(L). Аналогично, если в качестве L взять язык {1}+, то Li = s(L).
- Пусть L — КС-язык над алфавитом X, и h — гомоморфизм на X. Пусть s — подстановка, заменяющая каждый символ а из X языком, состоящим из единственной цепочки h(a), т.е. s(a) = {h(a)} для всех а из X. Тогда h(L) = s(L).
□
Обращение
КС-языки замкнуты также относительно обращения. Для доказательства этого факта использовать теорему о подстановках нельзя, но существует простая конструкция на основе грамматик.
Теорема 7.25. Если L — КС-язык, то и LK — КС-язык.
Доказательство. Пусть L— L(G) для некоторой КС-грамматики G = (V, Т, Р, S). Построим Gr = (V, Т, PR, S), где продукции PR представляют собой «обращения» продукций из Р. Таким образом, если А а — продукция G, то А —»с/ — продукция GR. С помощью индукции по длине порождений bGh6r нетрудно показать, что ЦСЯ) = Iя. По сути, все выводимые в GR цепочки являются обращениями цепочек, выводимых в G, и наоборот. Формальное доказательство оставляется в качестве упражнения. □
Пересечение с регулярным языком
КС-языки не замкнуты по пересечению. Это доказывает следующий простой пример. Пример 7.26. В примере 7.19 было выяснено, что язык
L = {0П1″2П | и > 1}
не является контекстно-свободным. Однако следующие два — контекстно-свободные. L = {0″1п2′ | л > 1, i> 1} L = {0’1П2П | л > 1, i > 1} Первый из них порождается следующей грамматикой. S—>AB Л->0Л1 | 01 В-+2В\2
В этой грамматике А порождает все цепочки вида 0П1П, а В— все последовательности двоек. Аналогична и грамматика для второго языка.
S->AB А OA | 0 В->\В2\ 12
Здесь А порождает все последовательности нулей, а В — цепочки вида 1П2П.
Однако L = L/f)L2. Чтобы в этом убедиться, заметим, что Lt требует равных количеств нулей и единиц в цепочках, тогда как L2 — равных количеств единиц и двоек. Поэтому цепочка из пересечения этих языков должна иметь поровну каждого из символов и, следовательно, принадлежать L.
Если бы КС-языки были замкнуты по пересечению, то мы могли бы доказать ложное утверждение о том, что L — контекстно-свободный язык. Полученное противоречие позволяет заключить, что КС-языки не замкнуты по пересечению. □
Вместе с тем, есть более слабое утверждение о пересечении. КС-языки замкнуты относительно операции «пересечение с регулярным языком». Формальное утверждение и его доказательство представлены в следующей теореме.
Теорема 7.27. Если L — КС-язык, a R — регулярный язык, то L П R является КС- языком.
Доказательство. Нам понадобится представление КС-языков с помощью МП- автоматов, а также конечноавтоматное представление регулярных языков. Данное доказательство обобщает доказательство теоремы 4.8, где для получения пересечения регулярных языков «параллельно запускались» два конечных автомата. Здесь конечный автомат запускается параллельно с МП-автоматом, и в результате получается еще один МП-автомат (рис. 7.9).
Магазин
Рис. 7.9. Для создания нового МП-автомата конечный автомат и МП-автомат запускаются параллельно
Формально, пусть
Р = (а, X, Г, <5;., qr, Z<), Ft.) — МП-автомат, допускающий L по заключительному состоянию, и пусть
А = (Qa, qA, Fa) — ДКА для R. Построим МП-автомат
Р’ = (Qr х а, X, Г, <5, (ф, Z0, Fp х
л
где S((q,p), a, JO определяется как множество всех пар ((г, s), у), где s = 8 А(р, а) и пара (г, у) принадлежит 8p(q, А, X).
Таким образом, для каждого перехода МП-автомата Р мы можем совершить такой же переход в МП-автомате Р\ дополнительно отслеживая состояние ДКА А во втором компоненте состояния Р’. Отметим, что а может быть символом из X или е. В первом случае
Л Л
8 А{р, а) = 8А(р, а), но если а = £, то 8 А(р, а) =р, т.е. А не меняет состояние, когда Р совершает е-переход.
С помощью простой индукции по числу переходов, совершаемых МП-автоматами, нетрудно доказать, что (qr, w, Z0) f^ (q, e, у) тогда и только тогда, когда ((q,,, qA), w, Z0) |-
Л
((q,p), £, У), где p = 8 A{p,w). Эти индукции оставляются в качестве упражнения. Но (q,p) является допускающим состоянием Я’тогда и только тогда, когда q— допускающее состояние Р и р — допускающее состояние А. Отсюда заключаем, что Р’ допускает w тогда и только тогда, когда его допускают Р и А вместе, т.е. w принадлежит L П R- О
Пример 7.28. На рис. 6.6 был определен МП-автомат F, допускающий по заключительному состоянию множество цепочек, которые состоят из i и е. Такие цепочки представляют минимальные нарушения правил, определяющих, в каком порядке слова if и else могут встречаться в С-программах. Назовем этот язык L. МП-автомат F был определен так:
Pf = ({p, q, г}, {/’, е}, {Z,x0}, sF,p,x0, {г}), где 8;. состоит из следующих правил.
St(p,e,Xo)=[(q,ZXo)}.
SF(q,i,Z)={(q,ZZ)}.
{(<7,£)}.
7> е,*0) = {(/■,£)}.
Теперь определим конечный автомат A = ({s, t), {/, е}, SA, s, {.?, t}), допускающий цепочки языка i’e*, т.е. все цепочки, в которых символы е следуют за i. Назовем этот язык R. Функция переходов 8А определяется следующими правилами:
а) SA(s, i) =
б) SA(s,e) = t;
в) 8A(t,e)-t.
Строго говоря, А не является ДКА, как предполагается в теореме 7.27, поскольку в нем отсутствует дьявольское состояние для случая, когда вход / получен в состоянии t. Однако такая же конструкция работает даже для НКА, так как МП-автомат, который строится, может быть недетерминированным. В данном же случае МП-автомат на самом деле детерминирован, хотя и «умирает» на некоторых входных последовательностях. Построим следующий МП-автомат.
Р = ({/>, д, г] х {s, t}, {/, е}, {Z, X0j, S, (р, s), Х0, {/■} х {s, t}) Переходы 8 перечислены ниже и проиндексированы номерами правил для МП-автомата F (числа от 1 до 4) и правил для ДКА А (буквы а, б, в). Если МП-автомат F совершает е- переход, правило для А не используется. Отметим, что правила для автомата Р строятся «ленивым» способом: правила для состояния строятся только тогда, когда обнаружено, что оно достигается из начального состояния Р.
- 8((p,s),E,X0)={((g,s),ZX0)}.
- 5{{q,s\i,Z) = {((g, s),ZZ)j.
3,6. %(q,s), e,Z)= {((<?, !),£)}.
- 5{(q, s), £,X0) = {(r, s), e)}. Отметим, что это правило никогда не будет применяться, поскольку невозможно вытолкнуть символ из магазина без е на входе, но как только Р видит е, вторым компонентом его состояния становится t.
в. S((g, l), e,Z)={((q,t),£)}. 4. 5{(д, t),£,Xfl)={((r, !),£)}.
Язык L П R представляет собой множество цепочек с некоторым количеством символов /, за которыми записаны символы е (на один больше), т.е. {z’nen+11 п > 0}. Как видим, такие блоки символов i с блоками символов е нарушают правила записи слов if и else в языке С. Этот язык, очевидно, является КС-языком, порождаемым грамматикой с продукциями S —> iSe | е.
Заметим, что МП-автомат Р допускает язык Lf]R. После помещения Z в магазин он заносит новые символы Z в магазин при чтении символов /’, оставаясь в состоянии (q, s). Как только на входе появляется е, он переходит в состояние (д, t) и начинает выталкивание из магазина. Он умирает, если видит i до того, как Х0 оказывается на вершине магазина. В последнем же случае он спонтанно переходит в состояние (г, t) и допускает. □
Поскольку КС-языки не замкнуты по пересечению, но замкнуты по пересечению с регулярным языком, то становятся понятными и свойства замкнутости относительно операций разности и дополнения. Перечислим эти свойства в следующей теореме.
Теорема 7.29. Пусть Lh L2 и L обозначают КС-языки, a R — регулярный язык. Справедливы следующие утверждения.
L-R является контекстно-свободным языком.
L может не быть КС-языком.
L\-L2 может не быть КС-языком.
Доказательство. Для п. 1 заметим, что L — R = L П R ■ Если R регулярно, то по теореме 4.5 регулярно и R . Тогда по теореме 7.27 L — R — КС-язык.
Для п. 2 предположим, что если L является КС-языком, то L — КС-язык. Но поскольку Li{\L2= 1л и Ц , и КС-языки замкнуты по объединению, получаем, что они
замкнуты и по пересечению. Однако это невозможно (см. пример 7.26).
Наконец, докажем п. 3. Очевидно, X* является КС-языком для любого алфавита X; нетрудно построить КС-грамматику или МП-автомат для этого регулярного языка. Таким образом, если бы язык Lj- L2 был контекстно-свободным для любых КС-языков L; и Ь2, то и X* — L должен быть КС-языком, если L — КС-язык. Однако X* — L = L при соответствующем алфавите X. Полученное противоречие к утверждению 2 доказывает, что Li — L2 не обязательно является КС-языком. □
7.3.5. Обратный гомоморфизм
Вспомним операцию «обратного гомоморфизма» из раздела 4.2.4. Если h— гомоморфизм, a L — произвольный язык, то h~\L) представляет собой множество таких цепочек w, для которых h(w) е L. Доказательство того, что регулярные языки замкнуты относительно обратного гомоморфизма, представлено на рис. 4.6. Там показано, как строится конечный автомат, обрабатывающий свои входные символы а путем применения к ним гомоморфизма h и имитации другого конечного автомата на цепочках h(a).
Замкнутость относительно обратного гомоморфизма можно доказать подобным путем, используя МП-автоматы вместо конечных автоматов. Однако при использовании МП-автоматов возникает проблема, которой не было с конечными автоматами. Действие конечного автомата при обработке входной цепочки заключается в изменении состояния, и это выглядит так же, как переход по одиночному входному символу.
Однако для МП-автоматов последовательность переходов может быть не похожа на переход по одному входному символу. В частности, за п переходов МП-автомат может вытолкнуть п символов из своего магазина, тогда как при одном переходе выталкивается только один. Таким образом, конструкция МП-автоматов, аналогичная представленной на рис. 4.6, будет существенно сложнее; она изображена эскизно на рис. 7.10. Дополнительная ключевая идея заключается в том, что, когда прочитан вход а, цепочка h(a) помещается в «буфер». Символы h(a) используются по одному и подаются на вход имитируемому МП-автомату. Когда буфер опустошается, основной МП-автомат читает свой следующий входной символ и применяет гомоморфизм к нему. Эта конструкция уточняется в следующей теореме.
Рис. 7.10. Построение МП-автомата, допускающего обратный гомоморфизм того, что допускает данный МП-автомат |
Теорема 7.30. Пусть L — КС-язык, h — гомоморфизм. Тогда h ‘(/,) является КС- языком.
Доказательство. Пусть h применяется к символам из алфавита X и порождает цепочки из 7’. Предположим также, что L — язык в алфавите Т, допускаемый по заключительному состоянию МП-автоматом Р = (Q, Т, Г, S, q0, Z0, F). Построим следующий новый МП-автомат Р’.
F = (Q’, X, Г, <У, (q0, £), Z0, F х {£}) (7.1)
Обозначения в определении Р’имеют следующий смысл.
g’есть множество пар (q, х), где q — состояние из Q, а х — суффикс (не обязательно собственный) некоторой цепочки h(a) для символа а из X. Таким образом, первый компонент состояния Р’ является состоянием Р, а второй— компонентом буфера. Предполагается, что буфер периодически загружается цепочкой h(a), а затем сокращается с головы по мере чтения его символов, которые подаются на вход имитируемому МП-автомату Р.
8′ определяется следующими правилами:
а) 8\(q, е), а,Х)= {((q, h(a)), X)} для всех символов а из Z, всех состояний q из Q и магазинных символов X из Г. Отметим, что здесь а не может быть е. Когда буфер пуст, Р’может прочитать свой следующий входной символ а и поместить h(a) в буфер;
б) если <5(7/, /;, X) содержит (р, у), где b е Т или b = е, то 8′((q, bx), е, X) содержит ((р, .г), у). Таким образом, Р’всегда имеет возможность имитации перехода Р, используя голову буфера. Если fee Т, то буфер должен быть непустым, но если b = е, то буфер может быть пустым.
Отметим, что в соответствии с определением (7.1) начальным состоянием Р’ является (q„, е), т.е. Р’стартует в начальном состоянии Р с пустым буфером.
Аналогично, допускающими состояниями Р’являются такие состояния (q, е), у которых q — допускающее состояние Р.
Следующее утверждение характеризует взаимосвязь Р» и Р.
* *
- (q0, h(w), Zo) |- (р, е, у) тогда и только тогда, когда ((q,h е), w, Z„) \-t ((р, е), е, у).
Доказательство в обоих направлениях проводится индукцией по числу переходов, совершаемых автоматами. При доказательстве достаточности заметим, что если буфер Р’ не пуст, то он не может читать свой следующий входной символ, а должен имитировать Р до тех пор, пока буфер не опустошится (хотя когда буфер пуст, он все еще может имитировать Р). Детали оставляются в качестве упражнения.
Приняв указанную взаимосвязь Р и Р\ заметим, что вследствие способа, которым определены допускающие состояния Р\ Р допускает h(w) тогда и только тогда, когда /»допускает w. Таким образом, ЦР’) = h’x(L(P)). □
7.3.6. Упражнения к разделу 7.3
Докажите, что КС-языки замкнуты относительно следующих операций:
а) (#) Init, определенная в упражнении 4.2.6, в. Указание. Начните с НФХ- грамматики для языка L;
б) (*!) операция L/a, определенная в упражнении 4.2.2. Указание. Начните с НФХ-грамматики для языка Z,;
в) (!!) Cycle, определенная в упражнении 4.2.11. Указание. Используйте конструкцию, основанную на МП-автомате.
Рассмотрим следующие два языка:
Lt = {anb2ncm \n,m>0}
L2 = {anbmc2m \n,m>Q}
а) покажите, что каждый из них является контекстно-свободным, построив для них КС-грамматики;
б) (!) укажите, является ли Lt f| L2 КС-языком. Ответ обоснуйте.
(!!) Покажите, что КС-языки не замкнуты относительно следующих операций:
а) (#) Мл, определенная в упражнении 4.2.6, а;
б) Мах, определенная в упражнении 4.2.6, б;
в) Half, определенная в упражнении 4.2.8;
г) Alt, определенная в упражнении 4.2.7.
Shuffle (Перемешивание) двух цепочек w их является множеством всех цепочек, которые можно получить путем произвольного чередования позиций w их. Точнее, shuffle(w, х) есть множество цепочек z, обладающих следующими свойствами.
Каждая позиция z может быть назначена w или х, но не обеим сразу.
Позиции z, назначенные w, при чтении слева направо образуют w.
Позиции z, назначенные х, при чтении слева направо образуют х. Например, если w = 01 и х= 110, то shuffle{0\, 110) есть множество цепочек {01110, 01101, 10110, 10101, 11010, 11001}. Для иллюстрации рассмотрим цепочку 10110. Ее вторая и пятая позиции назначены 01, а первая, третья и четвертая — 110. Цепочка 01110 может быть построена тремя способами: позиция 1 и одна из 2, 3, 4 назначается 01, а оставшиеся три в каждом случае — 110. Перемешивание языков, shuffle{Lh Ь2), определяется как объединение shuffle(w, х) по всем парам цепочек, w из Lt их из L2.
а) постройте shuffle(00, 111);
б) (*) укажите, что представляет собой shuffle(L,, L2), если L, -1(0*) и L2 = {0nln | и > 0};
в) (*!) докажите, что если L, и L2 — регулярные языки, то и shuffle(Lh L2) регулярен. Указание. Начните с конечных автоматов для Z,/ и L2;
г) (!) докажите, что если L является КС-языком, a R — регулярным языком, то shuffle(L, R) — КС-язык. Указание. Начните с МП-автомата для L и ДКА для R;
д) (!!) приведите контрпример, показывающий, что если Li mL2 — КС-языки, то shuffle(Lh L2) может не быть КС-языком.
(*!!) Цепочка у называется перестановкой цепочки х, если символы у можно переупорядочить и получить х. Например, перестановками цепочки х = 011 являются 110, 101 и 011. Если L — язык, то perm(L) — это множество цепочек, являющихся перестановками цепочек из L. Например, если L = {0″Г | п > 0}, то perm(L) представляет собой множество цепочек, в которых поровну символов 0 и 1:
а) приведите пример регулярного языка L над алфавитом {0, 1}, для которого perm(L) нерегулярен. Ответ обоснуйте. Указание. Попытайтесь найти регулярный язык, перестановками цепочек которого являются все цепочки с одинаковыми количествами 0 и 1;
б) приведите пример регулярного языка L в алфавите {0, 1, 2}, для которого perm(L) не является КС-языком;
в) докажите, что для каждого регулярного языка L в двухсимвольном алфавите perm(L) является КС-языком.
Приведите формальное доказательство теоремы 7.25 о том, что КС-языки замкнуты относительно обращения.
Дополните доказательство теоремы 7.27, показав, что (qР, w, Z0) (<7, е, у)
тогда и только тогда, когда {(qr, qA), w, Z„) ((<7, p), e, 7) и p = S (pA, w).
7.4. Свойства разрешимости КС-языков
Теперь рассмотрим, на какие вопросы о контекстно-свободных языках можно дать ответ. По аналогии с разделом 4.3, где речь шла о свойствах разрешимости регулярных языков, все начинается с представления КС-языка— с помощью грамматики или МП- автомата. Поскольку из раздела 6.3 нам известно о взаимных преобразованиях грамматик и МП-автоматов, можно предполагать, что доступны оба представления, и в каждом конкретном случае будем использовать более удобное.
Мы обнаружим, что разрешимых вопросов, связанных с КС-языками, совсем немного. Основное, что можно сделать, — это проверить, пуст ли язык, и принадлежит ли данная цепочка языку. Этот раздел завершается кратким обсуждением проблем, которые являются, как будет показано в главе 9, «неразрешимыми», т.е. не имеющими алгоритма разрешения. Начнем этот раздел с некоторых замечаний о сложности преобразований между грамматиками и МП-автоматами, задающими язык. Эти расчеты важны в любом вопросе об эффективности разрешения свойств КС-языков по данному их представлению.
7.4.1. Сложность взаимных преобразований КС-грамматик и МП-автоматов
Прежде чем приступать к алгоритмам разрешения вопросов о КС-языках, рассмотрим сложность преобразования одного представления в другое. Время выполнения преобразования является составной частью стоимости алгоритма разрешения в тех случаях, когда алгоритм построен для одной формы представления, а язык дан в другой.
В дальнейшем п будет обозначать длину представления МП-автомата или КС- грамматики. Использование этого параметра в качестве представления размера грамматики или автомата является «грубым», в том смысле, что некоторые алгоритмы имеют время выполнения, которое описывается точнее в терминах других параметров, например, число переменных в грамматике или сумма длин магазинных цепочек, встречающихся в функции переходов МП-автомата.
Однако мера общей длины достаточна для решения наиболее важных вопросов: является ли алгоритм линейным относительно длины входа (т.е. требует ли он времени, чуть большего, чем нужно для чтения входа), экспоненциальным (т.е. преобразование выполнимо только для примеров малого размера) или нелинейным полиномиальным (т.е. алгоритм можно выполнить даже для больших примеров, но время будет значительным).
Следующие преобразования линейны, как мы увидим далее, относительно размера входных данных.
Преобразование КС-грамматики в МП-автомат по алгоритму из теоремы 6.13.
Преобразование МП-автомата, допускающего по заключительному состоянию, в МП-автомат, допускающий по пустому магазину, с помощью конструкции из теоремы 6.11.
Преобразование МП-автомата, допускающего по пустому магазину, в МП-автомат, допускающий по заключительному состоянию, с использованием конструкции из теоремы 6.9.
С другой стороны, время преобразования МП-автомата в грамматику (теорема 6,14) существенно больше. Заметим, что п, общая длина входа, гарантированно является верхней границей числа состояний или магазинных символов, поэтому переменных вида [pXq], построенных для грамматики, может быть не более п. Однако время выполнения преобразования может быть экспоненциальным, если у МП-автомата есть переход, помещающий большое число символов в магазин. Отметим, что одно правило может поместить в магазин почти п символов.
Если мы вспомним построение продукций грамматики по правилу вида «5(q, а, X) содержит (г0, YiY2… У\у\ то заметим, что оно порождает набор продукций вида [qXr/,] —» «[roYiri][rtY2r2]…[г/с.lY^k] для всех последовательностей состояний rh …, гк. Поскольку к может быть близко к п, общее число продукций возрастает как п». Такое построение невозможно довести до конца для МП-автомата разумного размера, даже если он имеет всего одну цепочку, записываемую в магазин.
К счастью, этого наихудшего случая всегда можно избежать. Как предлагалось в упражнении 6.2.8, помещение длинной цепочки в магазин можно разбить на последовательность из не более, чем п шагов, на каждом из которых в магазин помещается всего один символ. Таким образом, если 5(q, а,Х) содержит (r0, Y,Y2…Yk), можно ввести новые состояния р2, р3, …, рк I■ Затем изменим (r0, YiY2…Yt) в 5{q, а,Х) на (pk-i, Yk ,Yk) и введем новые переходы
3(рк I, Е, Ук i) = {(Рк 2, Yk 2?к Л}, S(pk-2, е, Yk 2) = {{рк-з, Yk Л 2)} и так далее до S(p2, е, У2) = {(r0, Y,Y3)}.
Теперь в любом переходе не более двух магазинных символов. При этом добавлено не более п новых состояний, и общая длина всех правил перехода 8 выросла не более, чем в константу раз, т.е. осталась 0(п). Существует 0(п) правил перехода, и каждое порождает 0(п2) продукций, поскольку в продукциях, порожденных каждым правилом, должны быть выбраны всего два состояния. Таким образом, грамматика имеет длину 0(nJ) и может быть построена за кубическое время. Проведенный неформальный анализ резюмируется в следующей теореме.
Теорема 7.31. Существует алгоритм сложности 0(«3), который по МП-автомату Р строит КС-грамматику длиной не более 0(п). Эта грамматика порождает язык, допускаемый Р по пустому магазину. В дополнение, можно построить грамматику, которая порождает язык, допускаемый Р по заключительному состоянию. □
7.4.2. Временная сложность преобразования к нормальной форме Хомского
Алгоритмы могут зависеть от первичного преобразования в нормальную форму Хомского, поэтому посмотрим на время выполнения различных алгоритмов, использованных для приведения произвольной грамматики к НФХ. Большинство шагов сохраняют, с точностью до константного сомножителя, длину описания грамматики, т.е. по грамматике длиной п они строят другую длиной 0(п). «Хорошие» (с точки зрения затрат времени) преобразования перечислены в следующем списке.
С использованием подходящего алгоритма (см. раздел 7.4.3) определение достижимых и порождающих символов грамматики может быть выполнено за линейное время, 0(п). Удаление получившихся бесполезных символов требует О(п) времени и не увеличивает размер грамматики.
Построение цепных пар и удаление цепных продукций, как в разделе 7.1.4, требует времени 0(п2), и получаемая грамматика имеет размер 0(п2).
Замена терминалов переменными в телах продукций, как в разделе 7.1.5 (нормальная форма Хомского), требует времени 0{п) и приводит к грамматике длиной 0(п).
Разделение тел продукций длины 3 и более на тела длины 2 (раздел 7.1.5) также требует времени 0(п) и приводит к грамматике длиной О(п).
«Плохой» является конструкция из раздела 7.1.3, где удаляются е-продукции. По телу продукции длиной к можно построить 2k — 1 продукций новой грамматики. Поскольку к может быть пропорционально п, эта часть построения может занимать 0(2″) времени и приводить к грамматике длиной 0(2″).
Во избежание этого экспоненциального взрыва достаточно ограничить длины тел продукций. К каждому телу продукции можно применить прием из раздела 7.1.5, но только если в теле нет терминалов. Таким образом, в качестве предварительного шага перед удалением е-продукций рекомендуется разделить все продукции с длинными телами на последовательность продукций с телами длины 2. Этот шаг требует времени 0(п) и увеличивает грамматику только линейно. Конструкция из раздела 7.1.3 для удаления £-продукций будет работать с телами длиной не более 2 так, что время выполнения будет О(п) и полученная грамматика будет длиной 0(п).
С такой модификацией общего построения НФХ единственным нелинейным шагом будет удаление цепных продукций. Поскольку этот шаг требует 0(п2) времени, можно заключить следующее.
Теорема 7.32. По грамматике G длиной п можно найти грамматику в нормальной форме Хомского, эквивалентную G, за время 0(п2); полученная грамматика будет иметь длину 0(п2). □
7.4.3. Проверка пустоты КС-языков
Алгоритм проверки пустоты КС-языка L нам уже знаком. Чтобы определить, является ли стартовый символ S данной грамматики G для языка L порождающим, можно использовать алгоритм из раздела 7.1.2. L пуст тогда и только тогда, когда S не является порождающим.
Поскольку эта проверка весьма важна, рассмотрим детальнее, сколько времени требуется для поиска всех порождающих символов грамматики G. Пусть G имеет длину п. Тогда у нее может быть порядка п переменных, и каждый проход индуктивного обнаружения порождающих переменных может занимать 0(п) времени для проверки всех продукций G. Если на каждом проходе обнаруживается только одна новая порождающая переменная, то может понадобиться 0(п) проходов. Таким образом, простая реализация проверки на порождающие символы требует 0(п2) времени, т.е. является квадратичной.
Однако существует более аккуратный алгоритм, который заранее устанавливает структуру данных для того, чтобы обнаружить порождающие символы всего за СНп) времени. Структура данных (рис. 7.11) начинает с массива, индексированного переменными, как показано слева, который говорит, установлено ли, что переменная является порождающей. Массив на рис. 7.11 показывает, что переменная В уже обнаружена как порождающая, но о переменной А это еще неизвестно. В конце алгоритма каждая отметка «?» превращается в «нет», поскольку каждая переменная, не обнаруженная алгоритмом как порождающая, на самом деле является непорождающей.
Порождающая?
Рис. 7.11. Структуры данных для линейной проверки пустоты |
Для продукций предварительно устанавливается несколько видов полезных ссылок. Во-первых, для каждой переменной заводится список всех возможных позиций, в которых эта переменная встречается. Например, список для переменной В представлен сплошными линиями. Во-вторых, для каждой продукции ведется счетчик числа позиций, содержащих переменные, способность которых породить терминальную цепочку еще не учтена. Пунктирные линии представляют связи, ведущие от продукций к их счетчикам. Счетчики, показанные на рис. 7.11, предполагают, что ни одна из переменных в телах продукций еще не учитывалась, хотя уже и установлено, что В — порождающая.
Предположим, мы уже обнаружили, что В — порождающая. Мы спускаемся по списку позиций в телах, содержащих В. Для каждой такой позиции счетчик ее продукции уменьшаем на 1; позиций, которые нужны для заключения, что переменная в голове продукции тоже порождающая, остается на одну меньше.
Если счетчик достигает 0, то понятно, что переменная в голове продукции является порождающей. Связь, представленная точечными линиями, приводит к переменной, и эту переменную можно поместить в очередь переменных, о которых еще неизвестно, порождают ли они (переменная В уже исследована). Эта очередь не показана.
Обоснуем, что этот алгоритм требует 0(п) времени. Важными являются следующие утверждения.
Поскольку грамматика размера п имеет не более п переменных, создание и инициализация массива требует времени 0(п).
Есть не более п продукций, и их общая длина не превосходит п, поэтому инициализация связей и счетчиков, представленных на рис. 7.11, может быть выполнена за время 0(п).
Когда обнаруживается, что счетчик продукции получил значение 0, т.е. все позиции в ее теле являются порождающими, вся проделанная работа может быть разделена на следующие два вида.
Работа, выполненная для продукции: обнаружение, что счетчик обнулен, поиск переменной, скажем, А, в голове продукции, проверка, установлено ли, что эта переменная является порождающей, и помещение ее в очередь, если это не так. Все эти шаги требуют 0( 1) времени для каждой продукции, поэтому вся такая работа в целом требует 0(п) времени.
Работа, выполненная при посещении позиций в телах продукций, имеющих переменную А в голове. Эта работа пропорциональна числу позиций с переменной А. Следовательно, совокупная работа, выполненная со всеми порождающими переменными, пропорциональна сумме длин тел продукций, а это 0(п).
Отсюда делаем вывод, что общая работа, выполненная этим алгоритмом, есть 0(п).
Другие способы использования линейной проверки пустоты
Структура данных и счетчики, примененные в разделе 7.4.3 для проверки, является ли переменная порождающей, могут использоваться для обеспечения линейности времени некоторых других проверок из раздела 7.1. Назовем два важных примера.
Какие символы достижимы?
Какие символы являются е-порождающими?
7.4.4. Проверка принадлежности КС-языку
Проблема принадлежности цепочки w КС-языку L также разрешима. Есть несколько неэффективных способов такой проверки; они требуют времени, экспоненциального относительно \w\, в предположении, что язык L представлен заданной грамматикой или МП-автоматом, и размер представления считается константой, не зависящей от w. Например, начнем с преобразования какого-либо данного нам представления в НФХ-грамматику. Поскольку дерево разбора в такой грамматике является бинарным, при длине п слова w в дереве будет ровно 2п — 1 узлов, отмеченных переменными. Несложное индуктивное доказательство этого факта оставляется в качестве упражнения. Количество возможных деревьев и разметок их узлов, таким образом, «всего лишь» экспоненциально относительно п, поэтому в принципе их можно перечислить, и проверить, имеет ли какое-нибудь из деревьев крону w.
Существует гораздо более эффективный метод, основанный на идее «динамического программирования» и известный также, как «алгоритм заполнения таблицы» или «табуляция». Данный алгоритм известен как CYK-алгоритм[3] (алгоритм Кока-Янгера- Касами). Он начинает с НФХ-грамматики G = (У, Т, P,S) для языка L. На вход алгоритма подается цепочка w = aia2…a„ из Т*. За время 0{пх) алгоритм строит таблицу, которая говорит, принадлежит ли w языку L. Отметим, что при вычислении этого времени сама по себе грамматика рассматривается фиксированной, и ее размер вносит лишь константный сомножитель в оценку времени, измеряемого в терминах длины цепочки, проверяемой на принадлежность L.
В CYK-алгоритме строится треугольная таблица (рис. 7.12). Горизонтальная ось соответствует позициям цепочки w = aia2…am имеющей в нашем примере длину 5. Содержимое клетки, или вход таблицы X,j, есть множество таких переменных А, для которых
А => a,a, i…at. Заметим, в частности, что нас интересует, принадлежит ли S множеству
Х]„, поскольку это то же самое, что S => w, т.е. w е L.
Таблица заполняется построчно снизу вверх. Отметим, что каждая строка соответствует определенной длине подцепочек; нижняя— подцепочкам длины 1, вторая снизу — подцепочкам длины 2 и так далее до верхней строки, соответствующей одной подцепочке длиной п, т.е. w. Ниже обсуждается метод, с помощью которого вычисление одного входа требует времени 0(п). Поскольку всего входов п{п + 1)/2, весь процесс построения таблицы занимает 0(п3) времени. Алгоритм вычисления Х:/ таков.
Х[5 | ||||
Хы | х25 | |||
Х,3 | Х2v | х35 | ||
Х,2 | X» | Хи | х45 | |
Х„ | х22 | х33 | х44 | Xss |
аI | а2 | а3 | а4 | а5 |
Рис. 7.12. Таблица, построенная алгоритмом Кока-Янгера-Касами |
Базис. Вычисляем первую строку следующим образом. Поскольку цепочка, которая начинается и заканчивается в позиции /, представляет собой просто терминал а„ а грамматика находится в НФХ, единственный способ породить а, заключается в использовании продукции вида А —» а, грамматики G. Итак, Х„ является множеством переменных А, для которых А —> а, — продукция G.
Индукция. Пусть нужно вычислить X,, в (/ — /+ 1)-й строке, и все множества X в нижних строках уже вычислены, т.е. известны для всех подцепочек, более коротких, чем a,a, i…an и в частности, для всех собственных префиксов и суффиксов этой цепочки. Можно предполагать, что j — i > 0, поскольку случай j = i рассмотрен в базисе. Поэтому
любое порождение А => а,о,-/—0/ должно начинаться шагом А ВС. Тогда В порождает некоторый префикс строки а,а, /—Я/, скажем, В => ад,- для некоторого k < j. Кроме того, С порождает остаток a,a, t…ap т.е. С а^ iat,2…aj.
Приходим к выводу, что для того, чтобы А попало в Ху, нужно найти переменные В и Си целое к, при которых справедливы следующие условия.
- i<k<j.
В принадлежит Х,к.
С принадлежит Хк. д г
Л —> ВС — продукция в G.
Поиск таких переменных А требует обработки не более п пар вычисленных ранее множеств: (Хц, Xhi:J), (Хц-i, X^2,j) и т.д. до (X,j.h Хп). Таким образом, мы поднимаемся по колонке, расположенной под Хц, и одновременно спускаемся по диагонали (рис. 7.13).
Рис. 7.13. Вычисление Xjj требует совместной обработки столбца под Ху и диагонали справа от него |
Теорема 7.33. Вышеописанный алгоритм корректно вычисляет Хц для всех /’ и у. Таким образом, w б L(G) тогда и только тогда, когда S е Х,„. Кроме того, время выполнения алгоритма есть 0(пъ).
Доказательство. Представив базис и индуктивную часть алгоритма, мы объяснили, почему алгоритм находит корректные множества переменных. Рассмотрим время выполнения. Заметим, что нужно вычислить 0(п2) элементов таблицы, и каждое вычисление вовлекает сравнение и вычисление не более, чем п пар элементов. Важно помнить, что, хотя в каждом множестве Ху может быть много переменных, грамматика G зафиксирована и число ее переменных не зависит от п — длины проверяемой цепочки w. Таким образом, время сравнения элементов Х,к и Xt-ij и поиска переменных, входящих в Xjj, есть 0(1). Поскольку для каждого Хц возможно не более п таких пар, общее время составляет 0(п). □
Пример 7.34. Рассмотрим следующие продукции грамматики G в НФХ. S^AB\BC А->ВА\ а В СС | b С->АВ\а
Проверим, принадлежит ли цепочка baaba языку L(G). На рис. 7.14 показана таблица, заполненная для этой строки.
Для построения первой (нижней) строки используется базисное правило. Нужно рассмотреть лишь переменные с телом продукции а (это А и С) и телом b (это В). Таким образом, Х„ = Х44 = {В}, Х22 = Х33 = Х55 = {А, С}.
Во второй строке показаны значения Xt2, Х23, Х34 и Х45. Рассмотрим, например, как вычисляется Х,2. Цепочку Ьа, занимающую позиции 1 и 2, можно разбить на непустые подцепочки единственным способом. Первая должна занимать позицию 1, вторая— позицию 2. Для того чтобы переменная порождала Ьа, она должна иметь продукцию с телом, первая переменная которого принадлежит Хц = {6} (т.е. порождает Ь), а вторая — Х22 = {А, С} (т.е. порождает а). Таким телом может быть только ВА или ВС. Просмотрев грамматику, находим, что с такими телами там есть только продукции А ВА и S —> ВС. Таким образом, две головы, А и S, образуют Х12.
{S, A, Q
{S, А, С}
{В} {В}
{В} {S, С}
{В} {A, Q {A, Q {В} {A, Q
b a a b а
Рис. 7.14. Таблица для цепочки baaba, построенная алгоритмом Кока-Янгера-Касами
В качестве более сложного примера рассмотрим вычисление Х24. Цепочку aab в позициях с 2 по 4 можно разбить, заканчивая первую подцепочку в 2 или в 3, т.е. в определении Х24 можно выбрать к = 2 или к = 3. Таким образом, нужно рассмотреть все тела в ХпХ34 U Х23Х44. Этим множеством цепочек является {А, С}{5, С} U {В}{В} = {AS, AC, CS,
СС, ВВ}. Из пяти цепочек этого множества только СС является телом; его голова — В. Таким образом, Х24 = {В}. □
7.4.5. Обзор неразрешимых проблем КС-языков
В следующих главах излагается замечательная теория, позволяющая доказать формально, что существуют проблемы, которые нельзя разрешить никаким алгоритмом, выполняемым на компьютере. Используем ее для того, чтобы показать, что многие элементарные вопросы о грамматиках и КС-языках не имеют алгоритма решения; они называются «неразрешимыми проблемами». Сейчас же ограничимся следующим списком наиболее значительных неразрешимых вопросов о контекстно-свободных грамматиках и языках.
- Неоднозначна ли данная КС-грамматика G?
- Является ли данный КС-язык существенно неоднозначным?
- Пусто ли пересечение двух КС-языков?
- Равны ли два данных КС-языка?
- Равен ли 2* данный КС-язык, где 2 — алфавит этого языка?
Отметим, что вопрос 1 о неоднозначности отличается от остальных тем, что это вопрос о грамматике, а не о языке. Все остальные вопросы предполагают, что язык представлен грамматикой или МП-автоматом, но это все равно вопросы о языке (или языках). Например, в противоположность вопросу 1 вопрос 2 требует по данной грамматике G (или МП-автомату) определить, существует ли некоторая эквивалентная ей однозначная грамматика G’. Если G сама по себе однозначна, то ответом, безусловно, будет «да», но если G неоднозначна, то для языка грамматики G может существовать другая грамматика G’, которая однозначна, как было с грамматиками выражений в примере 5.27.
7.4.6. Упражнения к разделу 7.4
7.4.1. Постройте алгоритмы разрешения следующих проблем:
а) (*) конечен ли язык L(G) данной грамматики G? Указание. Используйте лемму о накачке;
б) (!) определить, содержит ли язык L(G) данной грамматики G не менее 100 цепочек;
в) (!!) по данной грамматике G и ее переменной А определить, существует ли выводимая цепочка, которая начинается символом А. Указание. Напомним, что переменная А может впервые появиться в середине некоторой выводимой цепочки, а затем все символы слева от нее могут породить е.
1А.1. Используйте технику, описанную в разделе 7.4.3, для построения линейных по времени алгоритмов разрешения следующих вопросов о КС-грамматиках.
- Какие символы встречаются в выводимых цепочках?
- Какие символы являются £-порождающими?
Примените CYK-алгоритм к грамматике G из примера 7.34, чтобы определить, принадлежат ли L(G) следующие цепочки:
а) (*) ababa;
б) baaab;
в) aabab.
(*) Покажите, что для любой НФХ-грамматики все деревья разбора цепочек длиной п имеют 2/7-1 внутренних узлов (отмеченных переменными).
7.4.5. (!) Измените CYK-алгоритм так, чтобы он сообщал, сколько различных деревьев вывода у данной цепочки, а не просто, принадлежит ли она языку грамматики.
Резюме
Удаление бесполезных символов. Переменную можно удалить из КС-грамматики, если она не порождает ни одной терминальной цепочки или не встречается в цепочках, выводимых из стартового символа. Для корректного удаления таких бесполезных символов нужно сначала проверить, порождает ли каждая переменная терминальную цепочку, и удалить те, которые не порождают. Только после этого удаляются переменные, которые не выводятся из стартового символа.
Удаление цепных и е-продукций. По данной КС-грамматике G можно найти еще одну КС-грамматику, которая порождает тот же язык, за исключением цепочки £, но не содержит цепных продукций (с единственной переменной в качестве тела) и е-продукций (с телом £).
Нормальная форма Хомского. По данной КС-грамматике G можно найти еще одну КС-грамматику, которая порождает тот же язык, за исключением цепочки Е, и находится в нормальной форме Хомского: нет бесполезных символов, и тело каждой продукции состоит либо из двух переменных, либо из одного терминала.
Лемма о накачке. В любой достаточно длинной цепочке КС-языка можно найти короткую подцепочку, два конца которой можно синхронно «накачивать», т.е повторять произвольное число раз. Хотя бы одна из накачиваемых цепочек не равна £. Эта лемма, а также ее более мощная версия, которая называется леммой Огдена и приводится в упражнении 7.2.3, дают возможность доказывать, что многие языки не являются контекстно-свободными.
Операции, сохраняющие контекстно-свободные языки. КС-языки замкнуты относительно подстановки, объединения, конкатенации, замыкания (*), обращения и обратного гомоморфизма. КС-языки не замкнуты относительно пересечения и дополнения, но пересечение КС-языка с регулярным всегда является КС-языком.
Проверка пустоты КС-языка. Существует алгоритм, который по данной грамматике G определяет, порождает ли она какие-нибудь цепочки. Аккуратная реализация этой проверки выполняется за время, прямо пропорциональное размеру самой грамматики.
Проверка принадлежности КС-языку. Алгоритм Кока-Янгера-Касами определяет, принадлежит ли данная цепочка данному КС-языку. Если язык зафиксирован, эта проверка требует времени 0(п3), где п — длина проверяемой цепочки.
Литература
Нормальная форма Хомского впервые описана в [2], нормальная форма Грейбах— в [4], хотя конструкция, описанная в упражнении 7.1.11, принадлежит Полу (М. С. Paull).
Многие фундаментальные свойства контекстно-свободных языков установлены в [1]. Среди них лемма о накачке, основные свойства замкнутости, а также проверки для простых вопросов, таких как пустота и конечность КС-языка. Результаты о незамкнутости относительно пересечения и дополнения происходят из работы [6], а дополнительные результаты о замкнутости, включая замкнутость КС-языков относительно обратного гомоморфизма, — из [3]. Лемма Огдена предложена в [5].
Алгоритм Кока-Янгера-Касами имеет три независимых источника. Работа Кока распространялась частным образом и не была опубликована. Версия по сути того же алгоритма, записанная Касами, появилась только в закрытом докладе Воздушных Сил США. И лишь работа Янгера была опубликована в [7].
- Bar-Hillel, М. Perles, and Е. Shamir, «On formal properties of simple phrase-structure grammars», Z. Phonetic. Sprachwiss. Kommunikationsforsch. 14 (1961), pp. 143-172.
- Chomsky, «On certain formal properties of grammars», Information and Control2:2 (1959), pp. 137-167. (Хомский H. О некоторых формальных свойствах грамматик. — Кибернетический сборник, вып. 5. — М.: ИЛ, 1962. — С. 279-311.)
- Ginsburg and G. Rose, «Operations which preserve definability in languages», J. ACM 10:2 (1963), pp. 175-195. (Гинзбург С., Роуз Дж. Об инвариантности классов языков относительно некоторых преобразований. — Кибернетический сборник, Новая серия, вып. 5, — М.: Мир, 1968, —С. 138-166.)
- Greibach, «A new normal-form theorem for context-free phrase structure grammars», J. ACM 12:1 (1965), pp. 42-52.
- Ogden, «A helpful result for proving inherent ambiguity», Mathematical Systems Theory 2:3 (1969), pp. 31^12. (ОгденУ. Результат, полезный для доказательства существенной неоднозначности. — сб. «Языки и автоматы». — М.: Мир, 1975. — С. 109-113.)
- Scheinberg, «Note on the boolean properties of context-free languages», Information and Control 3:4 (1960), pp. 372-375.
- H. Younger, «Recognition and parsing of context-free languages in time n3«, Information and Control 10:2 (1967), pp. 189-208. (Янгер Д. Распознавание и анализ контекстно-свободных языков за время п . — Сб. «Проблемы математической логики». — М.: Мир, 1970. — С. 344-362.)
[1] Напомним, что в русскоязычной литературе был принят термин «лемма о разрастании», но «накачка», на наш взгляд, точнее отражает суть происходящего. — Прим. ред.
[2] Напомним, что это п есть константа, обеспеченная леммой о накачке и не имеющая ничего общего с локальной переменной п, использованной в определении языка!.
[3] Он назван по фамилиям трех авторов (J. Cocke, D. Younger и Т. Kasami), независимо пришедших к одной и той же, по сути, идее.