- Conmutar
- Computar
- Deducir
- Probabilidad
- Información
- Vectores
- Derivadas
- Optimizar
- Neuronas
- Generalizar
- Atención
- LLM
Capítulo 00 · Circuitos y autómatas
¿Cómo calcula una máquina, por dentro?
Debajo de cualquier programa hay interruptores. El álgebra de Boole, unas pocas puertas lógicas y un poco de memoria bastan para construir un sumador, un autómata finito y, al final, un procesador. Por el camino aparece el primer límite: hay patrones que ninguna máquina con memoria finita puede reconocer.
En este capítulo
Un modelo de lenguaje que corre en una tarjeta gráfica hace billones de operaciones por segundo, y cada una, en el fondo, está hecha de interruptores que están encendidos o apagados. ¿Cómo se pasa de un interruptor a una máquina que suma, recuerda y sigue un programa? La respuesta tardó un siglo en armarse, del álgebra de George Boole (1854) a los primeros ordenadores con programa almacenado (1948), y es el cimiento sobre el que se apoya todo lo demás de esta web.
La pieza clave salió de una tesis de máster. En 1937 Claude Shannon, con veintiún años, mostró que los circuitos de relés de las centralitas telefónicas obedecen exactamente el álgebra de Boole: un interruptor es una variable que vale o , dos interruptores en serie son un (y) y dos en paralelo, un (o). Diseñar un circuito pasó a ser cuestión de manipular fórmulas, y razonar con fórmulas, algo que podía hacer un circuito.
Basta una puerta
Una función booleana de entradas es cualquier regla . Hay muchas: cada una de las entradas posibles puede ir a o a , así que hay funciones, ya 65 536 para . Y sin embargo un puñado de piezas basta para construirlas todas; de hecho, basta una sola: la puerta NAND, «no y».
Toda función booleana se puede calcular con un circuito de puertas , y . También bastan solo puertas NAND.
Demostración
Para cada entrada con , se forma la conjunción , donde si y si . Por construcción, exactamente cuando . Así que
que vale justo en las entradas en que vale (si no hay ninguna, ). Es la forma normal disyuntiva. Para NAND basta con reconstruir las tres puertas:
la última por la ley de De Morgan, .
La demostración construye circuitos que pueden ser enormes, y Shannon probó en 1949 que, para la mayoría de las funciones, no hay remedio: hay funciones pero muchísimos menos circuitos pequeños, así que casi toda función de entradas necesita del orden de puertas. Las funciones que nos interesan son las raras excepciones con circuitos pequeños. La suma es una de ellas.
De las puertas a la aritmética
Para sumar dos números en binario se hace lo que se aprende en el colegio: columna a columna, llevándose. En la columna entran tres bits, , y el acarreo , y salen dos: la cifra del resultado y el acarreo siguiente . Con para el o exclusivo (que vale cuando lo vale exactamente una de sus entradas), el sumador completo es
Encadenar sumadores completos, con , calcula la suma de dos números e de bits:
Demostración
Comprobando las ocho entradas posibles se ve que el sumador completo escribe en binario la suma de sus tres bits: . Multiplicando por y sumando en ,
y la última suma es telescópica: vale .
Cada sumador completo cuesta cinco puertas (o nueve puertas NAND), así que sumar números de 64 bits lleva unos cientos de puertas. Multiplicar, comparar o calcular un es cuestión de más circuitos del mismo tipo. Lo que aún falta es la memoria.
La memoria, y los autómatas finitos
Un circuito cuya salida vuelve a su entrada puede recordar. Dos puertas NAND conectadas en bucle forman un biestable que guarda un bit hasta que se le ordena cambiarlo. Con de esos bits y un reloj que marca el paso, un circuito tiene estados posibles y, en cada tic, pasa de un estado a otro según el estado y lo que entra. Ese objeto, quitada la electrónica, es un autómata finito.
Un AFD es una tupla con un conjunto finito de estados , un alfabeto de entrada , una función de transición , un estado inicial y un conjunto de estados de aceptación . Lee una palabra símbolo a símbolo, , y la acepta si termina en . El conjunto de palabras aceptadas es el lenguaje .
La idea vino de un sitio inesperado: el modelo de neuronas de McCulloch y Pitts (1943), redes de unidades con umbral que Stephen Kleene analizó en 1951 para preguntarse qué «sucesos» podían detectar. La respuesta, los lenguajes que reconocen los autómatas finitos, tiene además una descripción muy concreta.
aaaabbbb: no hay ningún estado para «cuatro».Una expresión regular describe un conjunto de palabras con tres operaciones: unión (, una u otra), concatenación (, una detrás de otra) y la estrella de Kleene (, cualquier número de repeticiones). Por ejemplo, es «cualquier palabra que termine en ».
Un lenguaje se describe con una expresión regular si y solo si lo reconoce un autómata finito.
Para pasar de expresiones a autómatas conviene dejar que el autómata adivine. Un autómata no determinista (AFN) puede tener varias transiciones con el mismo símbolo, o ninguna, y acepta si alguna elección lleva a un estado de aceptación. Cada operación de una expresión se convierte entonces en una pequeña pieza de AFN (la construcción de Thompson, de 1968, todavía en el corazón de muchos motores de expresiones regulares). Adivinar parece dar más poder. No lo da:
Para todo AFN con estados hay un AFD que reconoce el mismo lenguaje con como mucho estados.
Demostración
El AFD lleva la cuenta de todos los estados en que podría estar el AFN. Sus estados son los subconjuntos ; empieza en ; al leer pasa a ; y acepta si . Por inducción en la longitud de la palabra, tras leer el AFD está exactamente en el conjunto de estados a los que el AFN puede llegar con , así que acepta si y solo si lo hace alguna ejecución del AFN. Hay subconjuntos.
La exponencial es real: el lenguaje «el -ésimo símbolo empezando por el final es un » tiene un AFN con estados, y todo AFD para él necesita al menos . Rabin y Scott recibieron el premio Turing en 1976 por este artículo, que además introdujo el no determinismo, una idea que una década después estaría en la base de la pregunta frente a .
Lo que no puede hacer la memoria finita
El autómata de la figura no se puede ampliar para reconocer para todo , por muchos estados que le demos. No es falta de ingenio: es un teorema.
Si es regular, hay un número tal que toda palabra con se puede partir como , con y , de forma que para todo .
Demostración
Sea el número de estados de un AFD para . Al leer los primeros símbolos de , el autómata pasa por estados, así que por el principio del palomar repite alguno: hay posiciones con . Sea los primeros símbolos, los siguientes y el resto. Leer lleva al autómata de al mismo estado, así que puede hacerlo cero veces o cien, y acabará donde acababa con : en un estado de aceptación.
Toma y supón que fuera regular, con constante . La palabra está en y, como , el trozo está formado solo por aes. Al bombearlo, tiene más aes que bes, y no está en . Contradicción. Un autómata finito no puede contar sin límite: para comprobar que hay tantas bes como aes tendría que recordar un número que puede ser arbitrariamente grande.
La jerarquía de Chomsky
En 1956 el lingüista Noam Chomsky se preguntó qué tipo de gramática podría describir una lengua humana, y en 1959 ya había ordenado los lenguajes formales en cuatro niveles. Cada tipo de gramática corresponde exactamente a un tipo de máquina, que solo se distinguen por su memoria:
| Tipo | Gramática | Máquina | Memoria | Ejemplo que no está en el nivel anterior |
|---|---|---|---|---|
| 3 | Regular | Autómata finito | Finita | |
| 2 | Independiente del contexto | Autómata con pila | Una pila | |
| 1 | Dependiente del contexto | Autómata linealmente acotado | Una cinta tan larga como la entrada | |
| 0 | Sin restricciones | Máquina de Turing | Una cinta ilimitada | El problema de la parada |
Para basta una pila: se apila una ficha por cada y se desapila una por cada . Las gramáticas independientes del contexto, escritas en la notación de Backus–Naur de ALGOL 60, describen la sintaxis de casi todos los lenguajes de programación, y por eso todo compilador empieza con un autómata finito que trocea el texto en símbolos y un autómata con pila que construye el árbol sintáctico. Las lenguas humanas resultaron más escurridizas: algunas construcciones, como las dependencias cruzadas del alemán de Suiza, quedan fuera de las gramáticas independientes del contexto. Sesenta años después, los modelos que mejor predicen el lenguaje no son gramáticas en absoluto, pero eso es otro capítulo.
La máquina de debajo
Con sumadores, memoria y un autómata finito que los coordine se puede construir un ordenador. En 1945 John von Neumann describió el diseño del EDVAC: una memoria que guarda a la vez los datos y el programa, una unidad que hace la aritmética y una unidad de control que repite siempre el mismo ciclo. El 21 de junio de 1948 el «Baby» de Mánchester fue el primer ordenador que ejecutó un programa guardado en su propia memoria.
- Buscar: leer de la memoria la instrucción a la que apunta el contador de programa, y avanzar el contador.
- Decodificar: el autómata de control averigua qué operación es y a qué celda de memoria se refiere.
- Ejecutar: el sumador o la memoria hacen el trabajo, y el ciclo vuelve a empezar.
322 significa «suma el contenido de la celda 22». Avanza paso a paso por el ciclo de búsqueda, decodificación y ejecución, y mira cómo el contador de programa salta hacia atrás para repetir un bucle.Un ordenador real es, en sentido estricto, un autómata finito: con bits de memoria tiene como mucho estados. Pero con 16 gigabytes, es del orden de , y es un número que nada en el universo puede enumerar. Tiene más sentido pensar en la memoria como una cinta que siempre se puede alargar. Esa idealización, la cinta infinita, es exactamente la máquina de Turing.
Referencias
- G. Boole (1854). An Investigation of the Laws of Thought. Walton and Maberly.
- C. E. Shannon (1938). «A Symbolic Analysis of Relay and Switching Circuits». Transactions of the AIEE, 57(12).
- W. S. McCulloch y W. Pitts (1943). «A Logical Calculus of the Ideas Immanent in Nervous Activity». Bulletin of Mathematical Biophysics, 5.
- J. von Neumann (1945). First Draft of a Report on the EDVAC.
- C. E. Shannon (1949). «The Synthesis of Two-Terminal Switching Circuits». Bell System Technical Journal, 28(1).
- S. C. Kleene (1956). «Representation of Events in Nerve Nets and Finite Automata». En Automata Studies, Princeton University Press.
- N. Chomsky (1956). «Three Models for the Description of Language». IRE Transactions on Information Theory, 2(3).
- N. Chomsky (1959). «On Certain Formal Properties of Grammars». Information and Control, 2(2).
- M. O. Rabin y D. Scott (1959). «Finite Automata and Their Decision Problems». IBM Journal of Research and Development, 3(2).
- Y. Bar-Hillel, M. Perles y E. Shamir (1961). «On Formal Properties of Simple Phrase Structure Grammars». Zeitschrift für Phonetik, Sprachwissenschaft und Kommunikationsforschung, 14.
- K. Thompson (1968). «Regular Expression Search Algorithm». Communications of the ACM, 11(6).
- J. E. Hopcroft, R. Motwani y J. D. Ullman (2006). Introduction to Automata Theory, Languages, and Computation, 3.ª ed. Addison-Wesley.