He visto varias implementaciones de "State Machines" en github. Por lo que yo entiendo, una máquina de estados toma datos que pueden o no transformar su estado en uno de un conjunto finito de otros estados. ¿Cómo es eso diferente de cualquier otro programa de computadora?
computer-science
finite-state-machine
CondiciónRacer
fuente
fuente
Respuestas:
Si quieres ser muy pedante, cada programa de computadora es una máquina de estados finitos, porque incluso si convierte toda la materia en el universo entero en un ordenador, y que todavía sólo tienen memoria finita, por tanto, una cantidad finita de estados, y una finita cantidad de transiciones entre esos estados.
Las máquinas de estado son modelos, al igual que el cálculo Lambda, las máquinas de Turing, las máquinas de acceso aleatorio, los sistemas de actores, los sistemas de objetos, etc. Algunos problemas se prestan a ser modelados por una máquina de estado, otros no.
Los procesos comerciales a menudo se modelaban como máquinas de estado incluso antes de que existieran las computadoras. Se prestan naturalmente a ese tipo de pensamiento.
fuente
Desde un punto de vista teórico, no es para nada diferente. Por supuesto, desde un punto de vista teórico, puede escribir cualquier programa en lenguaje ensamblador y funcionará igual de bien.
Si bien la computadora en la que se ejecuta su código puede ser matemáticamente equivalente a una máquina de estados muy, muy complicada, como lo es cualquier otro programa que se ejecute en cualquier otra computadora, hay muchos problemas cuya solución más elegante es una máquina de estados finitos simple cuyos estados y las transiciones tienen significados específicos de dominio que se le ocurrió al programador (a diferencia del compilador o el diseñador de hardware).
Por ejemplo, una forma clásica de implementar expresiones regulares es interpretar la expresión regular como una especificación para una máquina de estados finitos, construir una máquina de ese tipo y luego alimentarla con cadenas para aceptarla o rechazarla . En términos más generales, cada vez que desee que un objeto en su programa siempre tenga uno de un número finito de estados y haga cumplir que las transiciones entre esos estados siempre sucedan de maneras específicas, construir una máquina de estados podría ser la solución más elegante .
fuente
Algunas respuestas aquí enfatizan que en nuestro (probablemente) universo finito todo es finito, todos los programas de computadora se ejecutan en tiempo finito, por lo tanto, técnicamente todo es una máquina de estado finito. Eso es "técnicamente correcto (el mejor tipo de correcto)", pero también pierde completamente el punto.
La esencia es esta: - Algunos programas de computadora requieren más memoria de trabajo cuando obtienen entradas más grandes y complejas. Algunos no lo hacen.
Si se da cuenta de esto, obtendrá una visión teórico-informativa que puede permitirle escribir programas más eficientes y elegantes cuando encuentre el tipo de problema dado. También le permitirá reconocer el tipo de problema donde esto puede aplicarse.
Aquí hay dos ejemplos de juguetes:
Problema 1: un programa recibe una lista de caracteres en la entrada estándar. Después de procesar todos los caracteres, el programa debe imprimir si el número de caracteres "x" en la entrada fue impar o par .
Problema 2: un programa recibe una lista de caracteres en la entrada estándar. Una vez procesados todos los caracteres, el programa debe imprimir si el número de caracteres "x" en la entrada fue menor , igual o mayor que el número de caracteres "y".
Es posible que desee dejar de leer ahora, resolver los problemas en su lenguaje de programación favorito (o simplemente un pseudocódigo) y regresar más tarde.
...
Lo importante que puede haber notado es lo siguiente: para implementar la solución al problema 1 correctamente, solo necesita un poco de memoria. No tiene que calcular cuántas "x" ha procesado, solo si el número de "x" procesadas hasta ahora fue impar o par. Cuando encuentres otra "x", voltea el bit. Al final del programa, mire el bit e imprima la respuesta.
¿Su entrada contiene docenas de caracteres? Miles de personajes? ¿Personajes de Googolplex (hipotéticamente hablando, por supuesto)? No importa; un poco de memoria de trabajo seguirá siendo suficiente.
No puede hacer lo mismo con el problema 2. Al leer los caracteres, debe recordar la diferencia entre la cantidad de "x" y "y" ya procesadas; de lo contrario, no puede imprimir la respuesta correcta de manera confiable. Usted puede darse cuenta de que en realidad no es necesario recordar tanto el número de "x" 's e 'Y'' s - sólo su diferencia, hasta el momento; un valor entero que aumentará cuando encuentre otra "x", y disminuya cuando encuentre otra "y", pero aún así, si decide usar, por ejemplo, 32 bits de memoria para mantener este valor, puede obtener una entrada ( varios miles de millones de caracteres) que no puede procesar correctamente con la cantidad limitada de memoria dada.
Esto es lo que queremos decir cuando decimos que el problema 1 puede resolverse con una "máquina de estado" y que el problema 2 no. Una cantidad limitada de memoria es suficiente para una entrada de cualquier tamaño.
(Por supuesto, también podría escribir una solución ineficiente para el problema 1, donde trataría de contar todas las "x" y luego también podría tener un problema de falta de memoria. Pero la diferencia es que un solución eficaz al problema 1 existe , mientras que una solución de manera similar eficiente para el problema 2 hace no .)
¿Por qué es esto importante en la vida real?
Primero, a diferencia de estos dos ejemplos de juguetes, el dilema puede no estar entre literalmente un valor entero de un bit y uno, sino entre una estructura de datos grande y otra aún mayor. A veces, la estructura de datos "aún más grande" no cabe en la memoria de la computadora, o ralentiza suficientemente el programa, incluso para entradas realistas.
En segundo lugar, la solución que usa la máquina de estado probablemente será mucho más rápida. También escalará linealmente con la longitud de entrada; es decir, procesar una entrada 10 veces más larga requerirá 10 veces más tiempo (a diferencia de, por ejemplo, 100 veces más tiempo). Esa es una propiedad deseada cuando necesita procesar una gran cantidad de datos.
Tercero, el uso de memoria limitado frente a ilimitado tiene un impacto en la seguridad . Si escribe un programa que solo requiere memoria limitada, no tiene que preocuparse por los desbordamientos de memoria y cómo podrían abusarse de ellos para comprometer la seguridad de todo el sistema.
Cuarto, esto es parte de lo que debería ser un plan de estudios estándar de informática en cualquier escuela decente: lenguajes formales , autómatas , complejidad computacional , etc. Para comprender la imagen más amplia detrás del diseño de la computadora, en lugar de simplemente "uhh, puse algunos fragmentos de código de Internet juntos, realmente espero que funcione, pero no puedo decir con certeza".
Para aprovechar esta teoría, realmente no necesita ninguna máquina especial, ningún marco o biblioteca ... solo necesita darse cuenta de "oh, esta parte del problema puede resolverse realmente usando una cantidad finita de memoria" y escribir su programa (en su lenguaje de programación favorito) en consecuencia. Pero en algunas situaciones es mejor usar una biblioteca existente, para no tener que reinventar la rueda.
fuente
Como señalaron las otras respuestas, las máquinas de estado no tienen nada de especial. Sin embargo, con frecuencia es beneficioso afirmar explícitamente que nuestro programa implementa un FSM.
La programación consiste en encontrar muchas abstracciones adecuadas para un problema. Usar una abstracción implica hablar en términos de la abstracción en lugar de en términos de la implementación. Muchos procesos tienen un estado inherente, por ejemplo, el proceso de registro en un sitio web o el proceso de salida en una aplicación de comercio electrónico. Si tuviera que modelar esos procesos, dibujaría cajas conectadas por flechas en una pizarra, un diagrama de estado. Aquí, una máquina de estado sería una especie de patrón de diseño y hablar de máquinas de estado comunicaría claramente mi intención a mis colegas.
Los programas imperativos tienen un estado inherente, por lo que no siempre nos damos cuenta cuando introducimos el estado. Por ejemplo, en el lenguaje C, ciertas construcciones de lenguaje, como el operador de punto y coma, marcan un "punto de secuencia", que es una transición de estado y exige el orden entre operaciones. Las cosas son diferentes en entornos como lenguajes funcionales puros como Haskell o cuando se usan protocolos sin estado como HTTP. De repente, cualquier estado debe volverse explícito, y expresar explícitamente nuestro diseño como máquina de estados puede hacerlo más manejable.
Las máquinas de estados finitos juegan un papel importante en el análisis, ya que corresponden a expresiones regulares. La implementación manual de alguna expresión regular puede dar como resultado un código extremadamente complicado, que en el peor de los casos ni siquiera es correcto. Cuando nos damos cuenta de que estamos implementando una máquina de estado, podemos usar una variedad de técnicas de implementación conocidas para ayudarnos. Por ejemplo, podríamos hacer que el estado sea explícito y almacenar el estado actual en una variable. Alternativamente, podemos hacer que el estado esté implícito a través del flujo de control en nuestro lenguaje. He hecho ambas cosas en diferentes circunstancias, pero afirmar que estamos implementando una máquina de estados (que presenta transiciones de estado restringidas, un estado de inicio, estados finales conocidos, sin recursión y sin estado implícito a través de la asignación persistente de datos) en lugar de un programa sin restricciones Es más fácil de implementar y comprender.
Raramente usaría una biblioteca de máquinas de estado, ya que todos los lenguajes de programación que conozco facilitan la expresión correcta y eficiente de una máquina de estados en ese lenguaje. Pero hay excepciones: si bien los autómatas deterministas son fáciles de implementar, los autómatas no deterministas son bastante no triviales, ya que la máquina de estados puede estar en múltiples estados al mismo tiempo. El uso de una biblioteca que implementa NFA o las reescribe me permite ignorar estas dificultades y centrarme en cosas que realmente importan.
Más allá de los usos de las máquinas de estado como diseño y máquinas de estado en informática y teoría del lenguaje, en realidad no hay tantos usos. Los circuitos lógicos con estado vienen a la mente. El uso principal de las máquinas de estado para un programador es aprender a pensar en términos de estados y transiciones de estado. ¿Dónde tiene mi programa estados implícitos? ¿Implementé correctamente todas las transiciones de estado? ¿Me perdí algo y abrí un estado no válido? Tal pensamiento vuelve a ser especialmente relevante en la programación orientada a objetos, ya que los campos miembros de un objeto corresponden al estado, y los métodos pueden afectar las transiciones de estado. Dudaría en implementar explícitamente una máquina de estados en un objeto, pero una máquina de estados puede ser un modelo mental adecuado para el comportamiento.
La razón principal para escribir una biblioteca de máquinas de estado es para asegurarse de que ha entendido el tema, pero en la mayoría de las aplicaciones no las necesitaría o, más bien, las pasaría a mano.
fuente