Задача о выводе в контекстно-свободной грамматике, алгоритм Кока-Янгера-Касами — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Алгоритм Кока-Янгера-Касами)
Строка 1: Строка 1:
 
[[Файл:table.jpg|300px|thumb|right|Таблица разбора алгоритма для цепочки из шести символов. В клетку <tex>t_{34}</tex> должны быть помещены нетерминалы, из которых выводится фрагмент входной строки длиной четыре символа, начинающийся с <tex>a_{3}</tex>, т.е. это цепочка <tex>a_{3}a_{4}a_{5}a_{6}</tex>. Этот фрагмент тремя способами можно разбить на пары непустых соседних фрагментов: (1) <tex>a_{3}</tex> и <tex>a_{4}a_{5}a_{6}</tex>, (2): <tex>a_{3}a_{4}</tex> и <tex>a_{5}a_{6}</tex>, (3): <tex>a_{3}a_{4}a_{5}</tex> и <tex>a_{6}</tex>. Этим трем парам фрагментов соответствуют пары клеток, в которых могут стоять нетерминалы, из которых эти фрагменты выводятся: (1) <tex>t_{31}</tex> и <tex>t_{43}</tex>, (2): <tex>t_{32}</tex> и <tex>t_{52}</tex>, (3): <tex>t_{33}</tex> и <tex>t_{61}</tex>. Если в этих клетках находятся соответственно нетерминалы B и C и существует правило A&rarr;BC, то A заносится в <tex>t_{34}</tex>]]
 
[[Файл:table.jpg|300px|thumb|right|Таблица разбора алгоритма для цепочки из шести символов. В клетку <tex>t_{34}</tex> должны быть помещены нетерминалы, из которых выводится фрагмент входной строки длиной четыре символа, начинающийся с <tex>a_{3}</tex>, т.е. это цепочка <tex>a_{3}a_{4}a_{5}a_{6}</tex>. Этот фрагмент тремя способами можно разбить на пары непустых соседних фрагментов: (1) <tex>a_{3}</tex> и <tex>a_{4}a_{5}a_{6}</tex>, (2): <tex>a_{3}a_{4}</tex> и <tex>a_{5}a_{6}</tex>, (3): <tex>a_{3}a_{4}a_{5}</tex> и <tex>a_{6}</tex>. Этим трем парам фрагментов соответствуют пары клеток, в которых могут стоять нетерминалы, из которых эти фрагменты выводятся: (1) <tex>t_{31}</tex> и <tex>t_{43}</tex>, (2): <tex>t_{32}</tex> и <tex>t_{52}</tex>, (3): <tex>t_{33}</tex> и <tex>t_{61}</tex>. Если в этих клетках находятся соответственно нетерминалы B и C и существует правило A&rarr;BC, то A заносится в <tex>t_{34}</tex>]]
 +
 +
= Формальная грамматика =
 +
 +
'''Формальная грамматика''' - способ описания формального языка, то есть некоторого подмножества слов данного конечного алфавита.  Выделяют ''порождающие'' грамматики, состоящие из следующих компонентов:
 +
 +
* 1) Множество '''терминальных символов''' ('''терминалов''') - символов алфавита, слова над которым определяет грамматика, то есть символов, непосредственно присутствующих в словах языка.
 +
* 2) Множество '''нетерминальных символов''' ('''нетерминалов''') - объектов, выражающих некоторые структурные части языка, не имеющие конкретного представления как слова над алфавитом (таких, как формула или часть программы).
 +
* 3) Множество '''правил вывода''' ('''продукций''') - правил вида L &rarr; R, где:
 +
** L - непустая последовательность терминальных и нетерминальных символов, содержищий по крайней мере один нетерминал.
 +
** R - любая (возможно, пустая) последовательность терминальных и нетерминальных символов.
 +
* 4) S - стартовый нетерминал.
 +
 +
'''Выводом''' называется последовательность строк из терминалов и нетерминалов, такая, что:
 +
* Первая строка состоит из стартового нетерминала
 +
* Каждая следующая строка получена из предыдущей путем замена некоторой подстроки по некоторому правилу
 +
* Последняя строка состоит только из терминалов (и, следовательно, не может быть преобразована по правилу грамматики).
 +
 +
Существование в грамматике вывода для получения конкретного слова - критерий принадлежности слова языку, определяемому грамматикой.
 +
 +
=== Пример ===
 +
 +
Терминалы: a, b. Нетерминалы: S, A, B. Продукции:
 +
* S &rarr; AB
 +
* A &rarr; AB
 +
* AB &rarr; ba
 +
* A &rarr; a
 +
* B &rarr; b
 +
 +
Слова, выводимые в данной грамматике: ab, ba, abb, bab, abbb, babb, ...
 +
 +
Слова, невыводимые в данной грамматике: a, b, baa, baba, ...
 +
 
= Контекстно-свободная грамматика =
 
= Контекстно-свободная грамматика =
  
Контекстно-свободная грамматика (КС-грамматика, бесконтекстная грамматика) — частный случай формальной грамматики, у которой левые части всех правил являются одиночными нетерминалами.
+
'''Контекстно-свободная грамматика''' ('''КС-грамматика''', '''бесконтекстная грамматика''') — частный случай формальной грамматики, у которой левые части всех правил являются одиночными нетерминалами, то есть все её продукции имеют вид L &rarr; R, где L - нетерминал, а R - последовательность терминалов и нетерминалов.
Для того, чтобы определить контекстно-свободную грамматику, необходимо:
+
 
* 1) Задать конечное множество A - алфавит; его
+
=== Пример ===
элементы  называют символами, а конечные последовательности симво-
+
 
лов называют словами (в данном алфавите);
+
Терминалы: (, ). Нетерминалы: S. Продукции:
* 2) Разделить все символы алфавита A на две группы:  терми-
+
* S &rarr; SS
нальные ("окончательные") и нетерминальные ("промежуточные");
+
* S &rarr; ()
* 3) Выбрать один из нетерминальных символов, который будет считаться начальным;
+
* S &rarr; (S)
* 4) Указать конечное число правил грамматики(продукций) вида:
+
 
    K &rarr; X
+
Очевидно, что данная грамматика задает язык правильных скобочных последовательностей. Например, последовательность (()(())) может быть выведена следующим образом:
где K - некоторый нетерминальный символ, а X - слово, которое может состоять как из терминальных, так и не из терминальных символов.
+
* S &rarr; (S) &rarr; (SS) &rarr; (()(S)) &rarr; (()(()))
Выводом в контекстно-свободной грамматике называется последовательность слов X[0], X[1], ... ,X[n], где X[0] состоит только из начального символа, а каждое слово X[i+1] получается из X[i] заменой какого-либо нетерминального символа на  слово по одному из правил грамматики.
 
  
==Пример==
+
= Нормальная форма Хомского =
  
Пусть алфавит состоит из символов a, b и S, при этом S - стартовый символ, а и b - терминальные. Пусть в этой грамматике определены следующие правила:
+
'''Нормальная форма Хомского''' - нормальная форма КС-грамматик, в которой все продукции имеют вид:
* S &rarr; SS;
+
* A &rarr; a, где ''A'' - нетерминал, а ''a'' - терминал
* S &rarr; ab;
+
* A &rarr; BC, где ''A'', ''B'', ''C'' - нетерминалы, причем ''B'' и ''C'' не являются начальными нетерминалами
* S &rarr; aSb;
+
* S &rarr; ε, где S - начальный нетерминал и ε - пустая строка (данная продукция необходима, если в языке присуствует пустая строка)
Тогда в ней можно вывести слово ababab следующим образом:
 
  S &rarr; SS &rarr; Sab &rarr; SSab &rarr; abSab &rarr; ababab
 
При этом, например, слово bab невозможно вывести в этой грамматике.
 
  
= Задача о выводе =
+
Покажем, что любую КС-грамматику можно привести к нормальной форме Хомского. Рассмотрим продукцию этой грамматики: <tex>A \Rightarrow A_1 A_2 A_3 ... A_n</tex>, где <tex>A_i</tex> - терминалы или нетерминалы. Добавим к грамматике нетерминалы <tex>B_1 ... B_n</tex>, <tex>C_k</tex> для таких k, что <tex>A_k</tex> - нетерминал, и продукции вида
+
* <tex>A \Rightarrow B_1</tex>
Задача вывода в контекстно-свободной грамматике состоит в том, чтобы выяснить, можно ли вывести данное слово в этой КС-грамматике, т.е. выяснить принадлежность этого слова определяемому грамматикой языку. Для решения этой задачи существуют несколько способов, например, нисходящий анализ методом линейного спуска. Также применяется восходящий алгоритм синтаксического анализа Кока - Янгера - Касами.
+
* <tex>B_i \Rightarrow A_i B_{i+1}</tex> если <tex>A_i</tex> - нетерминал
 +
* <tex>B_i \Rightarrow C_i B_{i+1}</tex> и <tex>C_i \Rightarrow A_i</tex>, если <tex>A_i</tex> - терминал
  
 
= Алгоритм Кока-Янгера-Касами =
 
= Алгоритм Кока-Янгера-Касами =
Алгоритм является универсальным для всех КС-грамматик, которые должны быть приведены в нормальную форму Хомского без &epsilon;-правил. Правила такой грамматики имеют вид либо А&rarr;а, либо А&rarr;BC, где a - терминал, B и C нетерминалы ,не являющиеся начальными. Алгоритм использует только квадратную матрицу, т.е. <tex>O(n^2)</tex> памяти. В алгоритме осуществляется для каждой ячейки перебор по всем разделениям фрагмента строки, выводимого из нетерминалов в этой ячейке, и по всем элементам алфавита, поэтому сложность можно оценить как <tex>O(n^3 \cdot |G|)</tex>, где G - алфавит.
+
'''Алгоритм Кока-Янгера-Касами''' (''Cocke — Younger — Kasami algorithm'', '''CYK - алгоритм''') - универсальный алгоритм, позволяющий по слову узнать, выводимо ли оно в заданной КС-грамматике в нормальной форме Хомского.
 +
 
 +
Пусть дана строка <tex>a_1 a_2 ... a_n</tex>. Заведем трехмерный массив d, состоящий из логических значений, и  <tex>d[A][i,j] = true</tex> тогда и только тогда, когда из нетерминала <tex>A</tex> правилами грамматики можно вывести подстроку <tex>a_i a_{i+1} ... a_j</tex>. Тогда:
 +
* <tex>d[A][i,i] = true</tex>, если в грамматике присутствует правило <tex>A \Rightarrow a_i</tex>, иначе <tex>false</tex>
 +
* Остальные элементы массива заполняются динамически: <tex>d[A][i,j] = \bigvee\limits_{A \Rightarrow BC}\bigvee\limits_{k = i}^{j-1} d[B][i,k] \wedge d[C][k+1,j]</tex>. То есть, подстроку <tex>a_i...a_j</tex> можно вывести из нетерминала <tex>A</tex>, если существует продукция <tex>A \Rightarrow BC</tex> и такое <tex>k</tex>, что подстрока <tex>a_i...a_k</tex> выводима из <tex>B</tex>, а подстрока <tex>a_{k+1}...a_j</tex> - из <tex>C</tex>.
 +
 
 +
Значение <tex>d[S][1,n]</tex> содержит ответ на вопрос, выводима ли данная строка в данной грамматике.
 +
 
 +
Очевидно, что алгоритм работает за время <tex>O(n^3)</tex> (где <tex>n</tex> - длина строки) и требует <tex>O(n^2)</tex> памяти (обе оценки с точностью до константных множителей, зависящих от конкретной грамматики).
 +
 
 +
Заметим, что если массив будет хранить целые числа, а формулу динамики заменить на <tex>d[A][i,j] = \sum\limits_{A \Rightarrow BC}\sum\limits_{k = i}^{j-1} d[B][i,k] \cdot d[C][k+1,j]</tex>, то <tex>d[A][i,j]</tex> - количество способов получить подстроку <tex>a_i...a_j</tex> из нетерминала <tex>A</tex>.
  
Сам алгоритм состоит в построении треугольной матрицы разбора T по заданной входной строке '''<tex>a_1,  a_2,  \ldots,  a_n</tex>'''. В каждый элемент этой матрицы <tex>t_{ik}</tex> помещаются все нетерминалы, из которых можно вывести отрезок входной строки длины k, начинающийся  i-ым символом: '''<tex>a_i,  \ldots,  a_{i+k-1}</tex>'''.
+
Пусть <tex>P_{A \Rightarrow BC}</tex> - ''стоимость'' вывода по правилу <tex>A \Rightarrow BC</tex>. Тогда, если использовать формулу <tex>d[A][i,j] = \min\limits_{A \Rightarrow BC} \min\limits_{k = i}^{j-1}  ( d[B][i,k] + d[C][k+1,j] + P_{A \Rightarrow BC} )</tex>, то <tex>d[A][i,j]</tex> - минимальная стоимость вывода подстроки <tex>a_i...a_j</tex> из нетерминала <tex>A</tex>.
Элементы матрицы вычисляются следующим образом:
 
:: <tex>\forall</tex>i <tex>t_{i1}</tex> = { A | A &rarr; <tex>a_i</tex>};
 
:: <tex>\forall</tex>i < j <tex>t_{ij}</tex> = {A | A&rarr;BC и <tex>1 \leqslant k < j : B \in t_{ik}, C \in t_{i+k, j-k}</tex>}.
 
Действительно, в каждый элемент <tex>t_{i1}</tex> (в данном случае удобнее рассматривать первой нижнюю строку) помещаются все нетерминалы, для которых существует правило A &rarr; <tex>a_i</tex> Пусть теперь заполнены все строки до j-1-й включительно.
 
Рассмотрим элемент <tex>t_{ij}</tex>, соответствующий фрагменту &lt;<tex>a_1,\ldots, a_j </tex>&gt; входной строки. Разобьём его всеми способами на пары соседних строк &lt;<tex>a_i</tex>&gt; и &lt;<tex>a_{i+1}...a_j</tex>&gt;; &lt;<tex>a_ia_{i+1}</tex>&gt; и &lt;<tex>a_{i+2} ...a_j</tex>&gt;, и т.д. Каждому варианту разбиения соответствует пара элементов матрицы, в которых стоят нетерминалы, из которых могут быть выведены соответствующие строки. Пусть эта пара элементов – (t',t"). В рассматриваемый элемент <tex>t_{ij}</tex> помещаем нетерминал А, если среди правил грамматики есть правило А&rarr;ВС, и нетерминал В входит в элемент t', а С – входит в элемент t".
 
  
Входная строка принадлежит языку, порождаемому грамматикой, если в элементе <tex>t_{1n}</tex> встретится начальный нетерминал.
+
Таким образом, задача о выводе в КС-грамматике в нормальной форме Хомского является обобщением задачи динамического программирования на подотрезке.
  
=Литература=
+
= Ссылки =
  
 
* [http://www.intuit.ru/department/algorithms/mathformlang/7/]
 
* [http://www.intuit.ru/department/algorithms/mathformlang/7/]
 
* [http://en.wikipedia.org/wiki/CYK_algorithm Википедия - CYK algorithm]
 
* [http://en.wikipedia.org/wiki/CYK_algorithm Википедия - CYK algorithm]
 
* [http://www.ctc.msiu.ru/program/t-system/diploma/node39.html Алгоритм Кока-Янгера-Касами]
 
* [http://www.ctc.msiu.ru/program/t-system/diploma/node39.html Алгоритм Кока-Янгера-Касами]

Версия 06:49, 6 декабря 2011

Таблица разбора алгоритма для цепочки из шести символов. В клетку [math]t_{34}[/math] должны быть помещены нетерминалы, из которых выводится фрагмент входной строки длиной четыре символа, начинающийся с [math]a_{3}[/math], т.е. это цепочка [math]a_{3}a_{4}a_{5}a_{6}[/math]. Этот фрагмент тремя способами можно разбить на пары непустых соседних фрагментов: (1) [math]a_{3}[/math] и [math]a_{4}a_{5}a_{6}[/math], (2): [math]a_{3}a_{4}[/math] и [math]a_{5}a_{6}[/math], (3): [math]a_{3}a_{4}a_{5}[/math] и [math]a_{6}[/math]. Этим трем парам фрагментов соответствуют пары клеток, в которых могут стоять нетерминалы, из которых эти фрагменты выводятся: (1) [math]t_{31}[/math] и [math]t_{43}[/math], (2): [math]t_{32}[/math] и [math]t_{52}[/math], (3): [math]t_{33}[/math] и [math]t_{61}[/math]. Если в этих клетках находятся соответственно нетерминалы B и C и существует правило A→BC, то A заносится в [math]t_{34}[/math]

Формальная грамматика

Формальная грамматика - способ описания формального языка, то есть некоторого подмножества слов данного конечного алфавита. Выделяют порождающие грамматики, состоящие из следующих компонентов:

  • 1) Множество терминальных символов (терминалов) - символов алфавита, слова над которым определяет грамматика, то есть символов, непосредственно присутствующих в словах языка.
  • 2) Множество нетерминальных символов (нетерминалов) - объектов, выражающих некоторые структурные части языка, не имеющие конкретного представления как слова над алфавитом (таких, как формула или часть программы).
  • 3) Множество правил вывода (продукций) - правил вида L → R, где:
    • L - непустая последовательность терминальных и нетерминальных символов, содержищий по крайней мере один нетерминал.
    • R - любая (возможно, пустая) последовательность терминальных и нетерминальных символов.
  • 4) S - стартовый нетерминал.

Выводом называется последовательность строк из терминалов и нетерминалов, такая, что:

  • Первая строка состоит из стартового нетерминала
  • Каждая следующая строка получена из предыдущей путем замена некоторой подстроки по некоторому правилу
  • Последняя строка состоит только из терминалов (и, следовательно, не может быть преобразована по правилу грамматики).

Существование в грамматике вывода для получения конкретного слова - критерий принадлежности слова языку, определяемому грамматикой.

Пример

Терминалы: a, b. Нетерминалы: S, A, B. Продукции:

  • S → AB
  • A → AB
  • AB → ba
  • A → a
  • B → b

Слова, выводимые в данной грамматике: ab, ba, abb, bab, abbb, babb, ...

Слова, невыводимые в данной грамматике: a, b, baa, baba, ...

Контекстно-свободная грамматика

Контекстно-свободная грамматика (КС-грамматика, бесконтекстная грамматика) — частный случай формальной грамматики, у которой левые части всех правил являются одиночными нетерминалами, то есть все её продукции имеют вид L → R, где L - нетерминал, а R - последовательность терминалов и нетерминалов.

Пример

Терминалы: (, ). Нетерминалы: S. Продукции:

  • S → SS
  • S → ()
  • S → (S)

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

  • S → (S) → (SS) → (()(S)) → (()(()))

Нормальная форма Хомского

Нормальная форма Хомского - нормальная форма КС-грамматик, в которой все продукции имеют вид:

  • A → a, где A - нетерминал, а a - терминал
  • A → BC, где A, B, C - нетерминалы, причем B и C не являются начальными нетерминалами
  • S → ε, где S - начальный нетерминал и ε - пустая строка (данная продукция необходима, если в языке присуствует пустая строка)

Покажем, что любую КС-грамматику можно привести к нормальной форме Хомского. Рассмотрим продукцию этой грамматики: [math]A \Rightarrow A_1 A_2 A_3 ... A_n[/math], где [math]A_i[/math] - терминалы или нетерминалы. Добавим к грамматике нетерминалы [math]B_1 ... B_n[/math], [math]C_k[/math] для таких k, что [math]A_k[/math] - нетерминал, и продукции вида

  • [math]A \Rightarrow B_1[/math]
  • [math]B_i \Rightarrow A_i B_{i+1}[/math] если [math]A_i[/math] - нетерминал
  • [math]B_i \Rightarrow C_i B_{i+1}[/math] и [math]C_i \Rightarrow A_i[/math], если [math]A_i[/math] - терминал

Алгоритм Кока-Янгера-Касами

Алгоритм Кока-Янгера-Касами (Cocke — Younger — Kasami algorithm, CYK - алгоритм) - универсальный алгоритм, позволяющий по слову узнать, выводимо ли оно в заданной КС-грамматике в нормальной форме Хомского.

Пусть дана строка [math]a_1 a_2 ... a_n[/math]. Заведем трехмерный массив d, состоящий из логических значений, и [math]d[A][i,j] = true[/math] тогда и только тогда, когда из нетерминала [math]A[/math] правилами грамматики можно вывести подстроку [math]a_i a_{i+1} ... a_j[/math]. Тогда:

  • [math]d[A][i,i] = true[/math], если в грамматике присутствует правило [math]A \Rightarrow a_i[/math], иначе [math]false[/math]
  • Остальные элементы массива заполняются динамически: [math]d[A][i,j] = \bigvee\limits_{A \Rightarrow BC}\bigvee\limits_{k = i}^{j-1} d[B][i,k] \wedge d[C][k+1,j][/math]. То есть, подстроку [math]a_i...a_j[/math] можно вывести из нетерминала [math]A[/math], если существует продукция [math]A \Rightarrow BC[/math] и такое [math]k[/math], что подстрока [math]a_i...a_k[/math] выводима из [math]B[/math], а подстрока [math]a_{k+1}...a_j[/math] - из [math]C[/math].

Значение [math]d[S][1,n][/math] содержит ответ на вопрос, выводима ли данная строка в данной грамматике.

Очевидно, что алгоритм работает за время [math]O(n^3)[/math] (где [math]n[/math] - длина строки) и требует [math]O(n^2)[/math] памяти (обе оценки с точностью до константных множителей, зависящих от конкретной грамматики).

Заметим, что если массив будет хранить целые числа, а формулу динамики заменить на [math]d[A][i,j] = \sum\limits_{A \Rightarrow BC}\sum\limits_{k = i}^{j-1} d[B][i,k] \cdot d[C][k+1,j][/math], то [math]d[A][i,j][/math] - количество способов получить подстроку [math]a_i...a_j[/math] из нетерминала [math]A[/math].

Пусть [math]P_{A \Rightarrow BC}[/math] - стоимость вывода по правилу [math]A \Rightarrow BC[/math]. Тогда, если использовать формулу [math]d[A][i,j] = \min\limits_{A \Rightarrow BC} \min\limits_{k = i}^{j-1} ( d[B][i,k] + d[C][k+1,j] + P_{A \Rightarrow BC} )[/math], то [math]d[A][i,j][/math] - минимальная стоимость вывода подстроки [math]a_i...a_j[/math] из нетерминала [math]A[/math].

Таким образом, задача о выводе в КС-грамматике в нормальной форме Хомского является обобщением задачи динамического программирования на подотрезке.

Ссылки