¿Hay máquinas "pequeñas" que pueden coincidir eficientemente con expresiones regulares?

30

Es bien sabido que una expresión regular puede ser reconocida por un autómata finito no determinista de tamaño proporcional a la expresión regular, o por un FA determinista que es potencialmente exponencialmente más grande. Además, dada una cadena una expresión regular , la NFA puede probar la pertenencia en tiempo proporcional a, y el DFA puede probar la membresía en un tiempo proporcional a. La desaceleración para el NFA surge del hecho de que esencialmente necesitamos rastrear los conjuntos de estados posibles en los que podría estar el autómata, y la explosión exponencial para el DFA surge del hecho de que sus estados son elementos del conjunto de poder de los estados del NFAr | s | | r | El | s |sr|s||r||s|

¿Es posible eficientemente (es decir, en el tiempo mejor que , y espacio mejor que ) reconocer expresiones regulares, si permitimos el uso de máquinas más potentes que autómatas finitos? (Por ejemplo, ¿hay ganancias sucintas al reconocer idiomas regulares con autómatas pushdown o máquinas de contador?)O ( 2 | r | )O(|r||s|)O(2|r|)

Neel Krishnaswami
fuente
2
Cuando dice que el "NFA puede probar la membresía en tiempo proporcional a ", ¿quiere decir que una máquina RAM (determinista) que simula el NFA de la manera obvia toma tanto tiempo? ¿O hay alguna otra forma de definir el "tiempo de ejecución de un NFA" que no se refiere a otro modelo computacional? (Aparte de la definición sensata pero no muy útil que dice que el tiempo de ejecución de cualquier NFA para la cadena es .)s | s ||s||r|s|s|
Radu GRIGore
Sí, esa es la interpretación correcta de mi pregunta.
Neel Krishnaswami
2
Entonces me parece más natural simplemente preguntar esto: ¿Hay un algoritmo (en una máquina RAM) que decida si una cadena está en el lenguaje definido por la expresión regular que funciona en tiempo y espacio? (Especialmente si define el tiempo de ejecución de un autómata pushdown también en términos de una máquina RAM.)r o ( | s || r | ) o ( 2 | r | )sro(|s||r|)o(2|r|)
Radu GRIGore
1
No entiendo el problema exactamente. ¿Es la entrada una cadena sy una expresión regular r, y el problema es decidir si s está en el lenguaje definido por la expresión regular r?
Robin Kothari
@ Robin: sí, eso es todo. Me gustaría saber si puede hacer coincidir expresiones regulares de manera más eficiente que los autómatas finitos mediante el uso de más potencia computacional, o si las características adicionales (por ejemplo, pila, RAM) simplemente no ayudan.
Neel Krishnaswami

Respuestas:

20

Es bastante fácil cambiar el tiempo por el espacio, de la siguiente manera.

Convierta la expresión regular en un NFA: para concretar la comparación de algoritmos, asumiremos que es el número de estados NFA, de modo que su tiempo limitado para simular directamente el NFA es válido y su espacio destinado a ejecutar el DFA convertido también es válido siempre que trabaje en una RAM que pueda ocupar tanta memoria.O ( r s ) O ( 2 r )rO(rs)O(2r)

Ahora, divida los estados de la NFA (arbitrariamente) en subconjuntos de como máximo estados cada uno. Dentro de cada subconjunto , podemos indexar los subconjuntos de por números del al .S ir / k S i A i S i 0 2 r / k - 1kSir/kSiAiSi02r/k1

Construya una tabla donde y están en el rango de 0 a , es un símbolo de entrada y es (el índice numérico de) un subconjunto de . El valor almacenado en la tabla es (el índice numérico de) un subconjunto de : un estado está en si y solo si pertenece a y hay un estado en que transita a en el símbolo de entrada .i j k - 1 c A i S i S j y T [ i , j , c , A i ] y S j A i y cT[i,j,c,Ai]ijk1cAiSiSjyT[i,j,c,Ai]ySjAiyc

Para simular el NFA, mantenga índices, uno para cada , especificando el subconjunto de los estados en que puede alcanzarse mediante algún prefijo de la entrada. Para cada símbolo de entrada , use las tablas para buscar, para cada par , el conjunto de estados en que se puede alcanzar desde un estado en mediante una transición en , y luego use un binario u operación bit a bit los índices numéricos de estos conjuntos de estados para combinarlos en un solo subconjunto de estados de . Entonces, cada paso de la simulación lleva tiempo , y el tiempo total para la simulación esS i A i S i c i , j S j A i c S j O ( k 2 ) O ( s k 2 )kSiAiSici,jSjAicSjO(k2)O(sk2) .

El espacio requerido es el espacio para todas las tablas, que es . El análisis de tiempo y espacio es válido en cualquier RAM que pueda direccionar tanta memoria y que pueda realizar operaciones binarias en palabras que sean lo suficientemente grandes como para direccionar tanta memoria.O(k22r/k)

La compensación tiempo-espacio que obtienes de esto no coincide perfectamente con la simulación NFA, debido a la dependencia cuadrática de . Pero entonces, soy escéptico de que sea ​​el momento adecuado para la simulación de NFA: ¿cómo simular un solo paso de la NFA más rápido que mirar todas las transiciones (posiblemente cuadráticamente muchas) permitidas desde una actividad actualmente activa? estado a otro estado? ¿No debería ser ?O ( r s ) O ( r 2 s )kO(rs)O(r2s)

En cualquier caso, al permitir que varíe, puede obtener límites de tiempo en un continuo entre los límites de DFA y NFA, con menos espacio que el DFA.k

David Eppstein
fuente
Creo que su corrección es correcta, y su respuesta responde a mi pregunta. Sin embargo, la pregunta que quería hacer es cuánta potencia computacional adicional ayuda. (Por ejemplo, con un contador puede hacer coincidir una cadena en el espacio O (1).) Si no le importa, dejaré la pregunta abierta un poco más para ver si alguien sabe la respuesta a eso ....ak
Neel Krishnaswami
@Neel: Si la solución de David es la mejor que puede hacer una máquina RAM, entonces las pilas, los contadores, etc. no ayudarán. (Pero, por supuesto, solo dio límites superiores, no límites inferiores.)
Radu GRIGore
1
Por lo que puedo decir, mi solución utiliza "potencia adicional": se basa en búsquedas de tablas e índices enteros, algo que no está disponible en los modelos DFA o NFA. Así que realmente no entiendo cómo no responde esa parte de la pregunta.
David Eppstein
Aquí hay una forma alternativa de parametrizar esto. Supongamos que estamos en una máquina RAM con ancho de palabra , donde . Luego, la simulación de NFA toma tiempo y espacio. La simulación de DFA no es posible si (no hay suficiente espacio disponible). La construcción en esta respuesta establece y toma tiempo y usa todo el espacio disponible (es decir, algo cerca del espacio ). Básicamente está explotando el paralelismo de bits disponible en una máquina RAM para hacer la simulación NFA más rápido. w lg r O ( s r 2 ) O ( r / w ) r w k r / w O ( s r 2 / w 2 ) 2 wwwlgrO(sr2)O(r/w)rwkr/wO(sr2/w2)2w
DW
4

Esta no es una respuesta, pero es demasiado larga para un comentario. Estoy tratando de explicar por qué la pregunta, tal como se plantea, puede ser difícil de entender.

Hay dos maneras de definir la complejidad computacional de un dispositivo X .

La primera y más natural es intrínseca . Hay que decir cómo el dispositivo X usa la entrada, para que luego veamos cómo el tamaño n de la entrada afecta el tiempo de ejecución del dispositivo. También hay que decir qué cuenta como una operación (o paso ). Luego, simplemente dejamos que el dispositivo se ejecute en las operaciones de entrada y conteo.

El segundo es extrínseco . Definimos la complejidad computacional para otro dispositivo de Y y luego programamos Y para que actúe como un simulador para X . Dado que puede haber múltiples formas para que Y simule X , debemos agregar que se supone que debemos usar la mejor. Permítanme decir lo mismo con otras palabras: decimos que X toma tiempo en una entrada de tamaño n si existe un simulador de X implementado en la máquina Y que toma tiempo .f ( n )O(f(n))f(n)

Por ejemplo, una definición intrínseca para NFA dice que se requieren n pasos para procesar una cadena de longitud n ; Una definición extrínseca que utiliza una máquina RAM como dispositivo Y dice que el límite superior más conocido es probablemente lo que respondió David Eppstein. (De lo contrario, sería extraño que (1) la mejor implementación práctica señalada en la otra respuesta no use la mejor alternativa y (2) aquí nadie indique una mejor alternativa). Tenga en cuenta también que estrictamente hablando su dispositivo X es la expresión regular , pero dado que el NFA tiene el mismo tamaño, es seguro tomarlo como el dispositivo X que está viendo.

Ω(f(n))

Entonces, en cierto sentido, la mejor respuesta que puede esperar es una prueba en algo como el modelo de sonda celular de que simular un NFA necesita una cierta cantidad de tiempo. (Tenga en cuenta que si tiene en cuenta la conversión de NFA a DFA, necesita tiempo para anotar el gran DFA, por lo que la memoria no es el único problema allí).

Radu GRIGore
fuente
4

Incluso si crees que no hay nada nuevo o antiguo que aprender sobre la coincidencia de expresiones regulares, mira uno de los trabajos más bellos que he encontrado en mucho tiempo: una obra de teatro sobre expresiones regulares de S Fischer, F Huch y T Wilke, ICFP 2010.

(MMT Chakravarty merece el crédito por recomendar este documento).

EDITAR: La razón por la cual este artículo es relevante es que describe una nueva técnica (basada en la de Glushkov de los años 60) que evita construir el NFA completo (y mucho menos el DFA) correspondiente al RE. Lo que se hace, en cambio, se asemeja a ejecutar un algoritmo de marcado similar al conocido para decidir la aceptación de una palabra por un NFA en el árbol de sintaxis del RE. Las mediciones de rendimiento sugieren que esto es competitivo, incluso con la biblioteca re2 publicada recientemente por Google.

Kai
fuente
¡Un buen periódico para leer!
Hsien-Chih Chang 張顯 之
1

Echa un vistazo a este artículo de Russ Cox. Describe un enfoque basado en NFA, empleado por primera vez por Ken Thompson, mediante el cual una cadena de entrada s puede coincidir con una expresión regular r en el tiempo O (| s |. C ) y el espacio O (| r |. D ), donde c y d son constantes superior encuadernados. El artículo también detalla una implementación en C de la técnica.


fuente
2
No estoy convencido de que sea una descripción precisa del artículo. Parece estar construyendo el DFA a partir del NFA según sea necesario y almacenando en caché los resultados. Pero el tamaño del caché podría ser exponencial en r.
David Eppstein