Algoritmo Cocke-Kasami-Younger

Autómatas y lenguajes formales

Algoritmo Cocke-Kasami-Younger

Iniciamos con una gramática libre de contexto (evito un poco las siglas, que harían más tratable el texto, pero también apoyan a confundirse y pensar que se lee algo complicadísimo), que es un cuarteto como hemos definido con anterioridad:

G=⟨Σ,Γ,S,→⟩,G = \langle \Sigma, \Gamma, S, \rightarrow \rangle,

con

Σ\Sigma el alfabeto de la cadena de entrada (los símbolos terminales)

Γ\Gamma el alfabeto de las variables y terminales (es una combinación)

SS la variable inicial

→\rightarrow el conjunto de las producciones.

La gramática son las reglas para generar cadenas en el lenguaje L(G)L(G), pero ahora es la pregunta inversa ¿si yo les doy una cadena ww cómo saben que es parte de ese lenguaje, w∈L(G)w\in L(G)? En clase y en los ejercicios lo han hecho a pie, pero como nos gusta usar la computadora, y si la cadena tiene miles de caracteres, lo mejor es hacerlo por medio de un algoritmo.

Este algoritmo hecho por estos tres alegres compadres requiere que pongan su gramática en forma normal de Chomsky (vean el pdf que les mandé de ayuda, el que incluye el disco punk de Chomsky), esto es por la facilidad de hacer un árbol de acomodo con esta forma un poco más compacta.

Una notación útil antes de ver el algoritmo es el que caracteriza a las subcadenas de la cadena original α∈L\alpha\in L con longitud nn. Sea 0≤i<j≤n0\leq i < j \leq n, con lo que:

αi,j\alpha_{i,j}

es la subcadena de α\alpha que va de la posición i+1i+1 a la jj. Ti,j⊆ΓT_{i,j}\subseteq \Gamma el conjunto de variables (o no terminales) que generan la subcadena αi,j\alpha_{i,j}. Como pueden ver el algoritmo irá comprobando por cortes si la cadena pertenece al lenguaje.

El algoritmo puesto en pseudo código se ve más o menos así:

for $i:=0$ to $n-1$ do
    $T_{i,i+1}:=\emptyset$
    for all $A \rightarrow a \in G$ do
      if $a=\alpha_{i,i+1}$ then
        $T_{i,i+1}:= T_{i,i+1} \cup \{A\}$
  for $m:=2$ to $n$ do
    for $i:=0$ to $n-m$ do
      $T_{i,i+m}:=\emptyset$
      for $j:=i+1$ to $i+m-1$ do
        for $A\rightarrow BC \in G$ do
          if $B\in T_{i,j}\wedge C\in T_{j,i+m}$ then
            $T_{i,m}:= T_{i,i+m} \cup A$

No pongo todos los detalles como comentario pues no me alcanza el espacio, pero les explico con un ejemplo.

Imaginemos que ya tenemos nuestra gramática en la forma normal de Chomsky (tomo prestado el ejemplo de [web1]):

S−>AB|BCA−>BA|aB−>CC|bC−>AB|a\begin{aligned} S&->AB|BC\\ A&->BA|a\\ B&->CC|b\\ C&->AB|a\end{aligned}

A partir de esto se construye una tabla triangular donde cada hilera corresponde a la longitud de la subcadena (vamos a checar que w∈L(G)w\in L(G) por partes).

Acomodo de la cadena en la tabla a llenar y primeros Ti,i+1T_{i,i+1} llenos.

|  |  |  | {A,C}\{A,C\}
|  |  | {B}\{B\} |
|  | {A,C}\{A,C\} |  |
| {A,C}\{A,C\} |  |  |
{B}\{B\} |  |  |  |
bb | aa | aa | bb | aa

Les doy la cadena: baababaaba de longitud 5. Armamos la tabla triangular como se muestra en la figura 1. La palabra va acomodada en el orden, los valores que se llenan primero en el algoritmo, los Ti,i+1T_{i,i+1} son los de la diagonal invertida, como se muestra en la misma tabla. Esos valores corresponden a los no terminales que producen el no terminal correspondiente, como podemos ver de la gramática la única producción que lleva al terminal bb es B→bB\rightarrow b. Por otro lado, para obtener aa tenemos dos opciones: A→aA\rightarrow a y C→aC\rightarrow a.

El siguiente paso, una vez teniendo esto es ver por pares (como si estuviéramos viendo un árbol binario, ahora veremos el nodo padre de cada dos, yendo de izquierda a derecha). Los primeros dos cuadros de la hilera inferior los desarrollamos como si hiciéramos un producto, siempre por pares pues es la forma normal de Chomsky:

{B}{A,C}={BA,BC}\{B\} \{A,C\} = \{BA,BC\}

¿Qué variables producen este par de variables? Vemos de nuevo nuestras producciones de la gramática, vemos que S→BCS\rightarrow BC y A→BAA\rightarrow BA, entonces en el segundo cuadro de la última hilera ponemos este par de variables {S,A}\{S,A\}. Este es el término T0,2T_{0,2}

Las siguientes parejas (recuerden mantener el orden, no es lo mismo ACAC que CACA):

{A,C}∧{A,C}={AA,AC,CA,CC}\{A,C\}\wedge \{A,C\} = \{AA,AC,CA,CC\}

La única combinación que es posible es B→CCB\rightarrow CC, entonces el tercer cuadro de la penúltima hilera se escribe {B}\{ B\}. Esta es la entrada T1,3T_{1,3}.

Luego va {A,C}{B}⟹{AB,CB}\{ A,C\}\{B\} \implies \{AB,CB\} (el orden, acuérdense, el orden). ¿Que producciones generan estas combinaciones de variables? Hay dos que producen una misma combinación S→ABS\rightarrow AB y C→ABC\rightarrow AB, entonces en el cuarto cuadro de la antepenúltima hilera se pone {S,C}\{S,C\}, que es la entrada T2,4T_{2,4}

Por último para esa semi-diagonal vemos que {B}{AC}⟹{BA,BC}\{B\} \{AC\}\implies \{BA,BC\}, tenemos S→BCS\rightarrow BC y A→BAA\rightarrow BA , entonces en el último cuadro de la segunda hilera se pone {S,A}\{S,A\}. La tabla va como se ve en la figura 2.

Avance de la tabla del algoritmo CKY.

|  |  |  | {A,C}\{A,C\}
|  |  | {B}\{B\} | {S,A}\{S,A\}
|  | {A,C}\{A,C\} | {S,C}\{S,C\} |
| {A,C}\{A,C\} | {B}\{B\} |  |
{B}\{B\} | {S,A}\{S,A\} |  |  |
bb | aa | aa | bb | aa

Ahora, en los que siguen es donde hay que tener más cuidado, ya no es tan directa la regla de combinar las producciones de la izquierda y arriba, pues como la tabla tiene más entradas debemos tomar en cuenta las demás. Para facilitar el mostrarles como funciona el algoritmo numeraré la tabla triangular de la manera que se muestre en la figura 3.

Nomenclatura de los miembros de la tabla.

|  |  |  | T4,5T_{4,5}
|  |  | T3,4T_{3,4} | T3,5T_{3,5}
|  | T2,3T_{2,3} | T2,4T_{2,4} | T2,5T_{2,5}
| T1,2T_{1,2} | T1,3T_{1,3} | T1,4T_{1,4} | T1,5T_{1,5}
T0,1T_{0,1} | T0,2T_{0,2} | T0,3T_{0,3} | T0,4T_{0,4} | T0,5T_{0,5}
bb | aa | aa | bb | aa

Nos paramos en el cuadro T0,3T_{0,3}, la regla para las comparaciones es como sigue:

Ti,j=T0,3⟹compara(Ti,i+1∧Ti+1,i+m)∪(Ti,i+2∧Ti+2,i+m)=(T0,1∧T1,3)∪(T0,2,T2,3)={B}∧{B}∪{S,A}∧{A,C}={BB,SA,SC,AA,AC}\begin{aligned} T_{i,j} = T_{0,3} \overset{ compara}{\implies} &(T_{i,i+1}\wedge T_{i+1,i+m})\cup (T_{i,i+2}\wedge T_{i+2,i+m})\\ = &(T_{0,1}\wedge T_{1,3})\cup (T_{0,2},T_{2,3})\\ = &\{B\}\wedge \{B\} \cup \{S,A\}\wedge \{A,C\}\\ = &\{BB,SA,SC,AA,AC\}\end{aligned}

Esto quiere decir que ahora la producción más alejada a la izquierda con la más cercana arriba, y la producción más arriba con la contigua a la izquierda. ¿Alguna variable produce esas combinaciones de variables? Ninguna, entonces dejan vacía la casilla (o la marcan con símbolo vacío).

El siguiente cuadro sería el T1,4T_{1,4}:

Ti,j=T1,4⟹compara(Ti,i+1∧Ti+1,i+m)∪(Ti,i+2∧Ti+2,i+m)=(T1,2∧T2,4)∪(T1,3∧T3,4)={A,C}{S,C}∪{B}{B}={AS,AC,CS,CC,BB}\begin{aligned} T_{i,j} = T_{1,4} \overset{compara}{\implies} &(T_{i,i+1}\wedge T_{i+1,i+m})\cup (T_{i,i+2}\wedge T_{i+2,i+m})\\ = &(T_{1,2}\wedge T_{2,4})\cup (T_{1,3}\wedge T_{3,4})\\ = &\{A,C\}\{S,C\} \cup \{B\}\{B\}\\ = &\{AS,AC,CS,CC,BB\}\end{aligned}

¿Alguna variable genera una de esas combinaciones? Ahora sí, el B→CCB\rightarrow CC, entonces en ese cuadro se pone {B}\{B\}, es decir T1,4={B}T_{1,4}=\{B\}.

El que sigue es T2,5T_{2,5}

Ti,j=T2,5⟹compara(Ti,i+1∧Ti+1,i+m)∪(Ti,i+2∧Ti+2,i+m)=(T2,3∧T3,5)∪(T2,4∧T4,5)={A,C}{S,A}∪{S,C}{A,C}={AS,AA,CS,CA,SA,SC,CA,CC}\begin{aligned} T_{i,j} = T_{2,5} \overset{compara}{\implies} &(T_{i,i+1}\wedge T_{i+1,i+m})\cup (T_{i,i+2}\wedge T_{i+2,i+m})\\ = &(T_{2,3}\wedge T_{3,5})\cup (T_{2,4}\wedge T_{4,5})\\ = &\{A,C\}\{S,A\} \cup \{S,C\}\{A,C\}\\ = &\{AS,AA,CS,CA,SA,SC,CA,CC\}\end{aligned}

De nueva cuenta la única combinación posible es CCCC que viene de B→CCB\rightarrow CC, entonces T2,5={B}T_{2,5}=\{B\}. La tabla va como se muestre en la figura 4.

Avance de la tabla.

|  |  |  | {A,C}\{A,C\}
|  |  | {B}\{B\} | {S,A}\{S,A\}
|  | {A,C}\{A,C\} | {S,C}\{S,C\} | {B}\{B\}
| {A,C}\{A,C\} | {B}\{B\} | {B}\{B\} |
{B}\{B\} | {S,A}\{S,A\} | ∅\emptyset |  |
bb | aa | aa | bb | aa

El cuadro que sigue es el T0,4T_{0,4}:

Ti,j=T0,4⟹compara(Ti,i+1∧Ti+1,i+m)∪(Ti,i+2∧Ti+2,i+m)∪(Ti,i+3∧Ti+3,i+m)=(T0,1∧T1,4)∪(T0,2∧T2,4)∪(T0,3,X3,4)={B}{B}∪{S,A}{S,C}∪{⌀}{B}={BB,SS,SC,AS,AC}\begin{aligned} T_{i,j} = T_{0,4} \overset{compara}{\implies} &(T_{i,i+1}\wedge T_{i+1,i+m})\cup (T_{i,i+2}\wedge T_{i+2,i+m})\cup (T_{i,i+3}\wedge T_{i+3,i+m})\\ = &(T_{0,1}\wedge T_{1,4})\cup (T_{0,2}\wedge T_{2,4})\cup (T_{0,3},X_{3,4})\\ = &\{B\}\{B\} \cup \{S,A\}\{S,C\} \cup \{\varnothing\}\{B\}\\ = &\{BB,SS,SC,AS,AC\}\end{aligned}

No hay producción que genere esas combinaciones, entonces T0,4=⌀T_{0,4} = \varnothing, la que sigue sería T1,5T_{1,5}:

Ti,j=X1,5⟹compara(Ti,i+1∧Ti+1,i+m)∪(Ti,i+2∧Ti+2,i+m)∪(Ti,i+3∧Ti+3,i+m)=(T1,2∧T2,5)∪(T1,3∧T3,5)∪(T1,4∧T4,5)={A,C}{B}∪{B}{S,A}∪{B}{A,C}={AB,CB,BS,BA,BA,BC}\begin{aligned} T_{i,j} = X_{1,5} \overset{compara}{\implies} &(T_{i,i+1}\wedge T_{i+1,i+m})\cup (T_{i,i+2}\wedge T_{i+2,i+m})\cup (T_{i,i+3}\wedge T_{i+3,i+m})\\ = &(T_{1,2}\wedge T_{2,5})\cup (T_{1,3}\wedge T_{3,5})\cup (T_{1,4}\wedge T_{4,5})\\ = &\{A,C\}\{B\} \cup \{B\}\{S,A\} \cup \{B\}\{A,C\}\\ = &\{AB,CB,BS,BA,BA,BC\}\end{aligned}

Aquí sí hay ABAB dos veces y BABA: S→ABS\rightarrow AB, C→ABC\rightarrow AB y A→BAA\rightarrow BA, es decir X2,5={S,C,A}X_{2,5} = \{S,C,A\}.

Ahora vamos al jefe final:

Ti,j=T0,5⟹compara(Ti,i+1∧Ti+1,i+m)∪(Ti,i+2∧Ti+2,i+m)∪(Ti,i+3∧Ti+3,i+m)∪(Ti,i+4∧Ti+4,i+m)=(T0,1∧T1,5)∪(T0,2∧T2,5)∪(T0,3∧T3,5)∪(T0,4∧T4,5)={B}{S,C,A}∪{S,A}{B}∪{⌀}{S,A}∪{⌀}{A,C}={BS,BC,BA,SB,AB}\begin{aligned} T_{i,j} = T_{0,5} \overset{compara}{\implies} &(T_{i,i+1}\wedge T_{i+1,i+m})\cup (T_{i,i+2}\wedge T_{i+2,i+m})\cup (T_{i,i+3}\wedge T_{i+3,i+m})\cup (T_{i,i+4}\wedge T_{i+4,i+m})\\ = &(T_{0,1}\wedge T_{1,5})\cup (T_{0,2}\wedge T_{2,5})\cup (T_{0,3}\wedge T_{3,5})\cup (T_{0,4}\wedge T_{4,5})\\ = &\{B\}\{S,C,A\} \cup \{S,A\}\{B\} \cup \{\varnothing\}\{S,A\} \cup \{\varnothing\}\{A,C\}\\ = &\{BS,BC,BA,SB,AB\}\end{aligned}

Tres de esas producciones son posibles S→AB|BCS\rightarrow AB|BC, A→BAA\rightarrow BA y C→ABC\rightarrow AB, por lo tanto T0,5={S,A,C}T_{0,5}=\{S,A,C\}.

Se ha completado la tabla, y espero hayan visto el algoritmo. Como el cuadro T0,5T_{0,5} no es vacío e incluye SS, entonces la cadena está en el lenguaje. Fin.

La tabla final, si hay SS en el cuadro inferior de la derecha, se acepta la cadena.

|  |  |  | {A,C}\{A,C\}
|  |  | {B}\{B\} | {S,A}\{S,A\}
|  | {A,C}\{A,C\} | {S,C}\{S,C\} | {B}\{B\}
| {A,C}\{A,C\} | {B}\{B\} | {B}\{B\} | {S,C,A}\{S,C,A\}
{B}\{B\} | {S,A}\{S,A\} | ∅\emptyset | ∅\emptyset | {S,A,C}\{S,A,C\}
bb | aa | aa | bb | aa

Y ahora https://www.youtube.com/watch?v=oQHivjjOcnE, para sacar el estrés.

10 Kozen, Dexter C. “Automata and Computability” Springer (1997) https://web.cs.ucdavis.edu/~rogaway/classes/120/winter12/CYK.pdf https://courses.cs.washington.edu/courses/cse431/15sp/CKY.pdf