stringtranslate.com

Máquina de acceso aleatorio

En informática , una máquina de acceso aleatorio ( RAM o máquina RA ) es un modelo de computación que describe una máquina abstracta en la clase general de máquinas de registro . La máquina RA es muy similar a la máquina contadora pero con la capacidad añadida de "direccionamiento indirecto" de sus registros. Los "registros" son intuitivamente equivalentes a la memoria principal de una computadora común, excepto por la capacidad adicional de los registros para almacenar números naturales de cualquier tamaño. Al igual que la máquina contadora, la máquina RA contiene las instrucciones de ejecución en la parte de estado finito de la máquina (la llamada arquitectura Harvard ).

El equivalente de la máquina RA de la máquina universal de Turing  (con su programa en los registros y sus datos) se denomina máquina de programa almacenado de acceso aleatorio o máquina RASP. Es un ejemplo de la llamada arquitectura de von Neumann y es la que más se acerca al concepto común de computadora .

Junto con los modelos de máquina de Turing y de contramáquina , los modelos de máquina RA y de máquina RASP se utilizan para el análisis de complejidad computacional . Van Emde Boas (1990) denomina a estos tres modelos, junto con la máquina de punteros , modelos de "máquina secuencial", para distinguirlos de los modelos de " máquina de acceso aleatorio paralelo ".

Descripción informal

Una máquina RA consta de lo siguiente:

Para una descripción de un concepto similar, pero humorístico, véase el lenguaje de programación esotérico Brainfuck . [1]

Introducción al modelo

El concepto de una máquina de acceso aleatorio (RAM) comienza con el modelo más simple de todos, el llamado modelo de máquina contadora . Sin embargo, dos añadidos lo alejan de la máquina contadora. El primero mejora la máquina con la comodidad del direccionamiento indirecto; el segundo acerca el modelo a la computadora más convencional basada en acumuladores con la adición de uno o más registros auxiliares (dedicados), el más común de los cuales se llama "el acumulador".

Definición formal

Una máquina de acceso aleatorio (RAM) es un modelo abstracto de máquina computacional idéntico a una máquina contadora de múltiples registros con el añadido de direccionamiento indirecto. A discreción de la instrucción de la TABLA de su máquina de estados finitos , la máquina deriva la dirección de un registro "objetivo" (i) directamente de la instrucción misma, o (ii) indirectamente del contenido (por ejemplo, número, etiqueta) del registro "puntero" especificado en la instrucción.

Por definición: un registro es una ubicación con una dirección (una designación o localizador único y distinguible equivalente a un número natural) y un contenido  (un único número natural). Para mayor precisión, utilizaremos el simbolismo cuasiformal de Boolos-Burgess-Jeffrey (2002) para especificar un registro, su contenido y una operación en un registro:

Ejemplo: [3] +1 → 3; significa "El contenido del registro de origen con dirección "3", más 1, se coloca en el registro de destino con dirección "3" (aquí origen y destino son el mismo lugar). Si [3]=37, es decir, el contenido del registro 3 es el número "37", entonces 37+1 = 38 se colocará en el registro 3.
Ejemplo: [3] → 5; significa "El contenido del registro de origen con dirección "3" se coloca en el registro de destino con dirección "5". Si [3]=38, es decir, el contenido del registro 3 es el número 38, entonces este número se colocará en el registro 5. El contenido del registro 3 no se ve alterado por esta operación, por lo que [3] continúa siendo 38, ahora igual que [5].

Definición: Una instrucción directa es aquella que especifica en la propia instrucción la dirección del registro de origen o destino cuyo contenido será objeto de la instrucción. Definición: Una instrucción indirecta es aquella que especifica un "registro puntero", cuyo contenido es la dirección de un registro "objetivo". El registro objetivo puede ser un origen o un destino (las diversas instrucciones COPY proporcionan ejemplos de esto). Un registro puede direccionarse a sí mismo indirectamente.

A falta de un estándar/convención, este artículo especificará "directo/indirecto", abreviado como "d/i", como parámetro (o parámetros) en la instrucción:
Ejemplo: COPY ( d , A, i , N ) significa que d obtiene directamente la dirección del registro de origen (registro "A") de la instrucción misma, pero indirectamente i obtiene la dirección de destino del registro puntero N. Supongamos que [N]=3, entonces el registro 3 es el destino y la instrucción hará lo siguiente: [A] → 3.

Definición: La instrucción utiliza el contenido del registro fuente . La dirección del registro fuente se puede especificar (i) directamente mediante la instrucción o (ii) indirectamente mediante el registro puntero especificado por la instrucción.

Definición: El contenido del registro del puntero es la dirección del registro "objetivo".

Definición: El contenido del registro puntero apunta al registro de destino  ; el "objetivo" puede ser un registro de origen o de destino.

Definición: El registro de destino es donde la instrucción deposita su resultado. La dirección del registro de origen puede especificarse (i) directamente mediante la instrucción o (ii) indirectamente mediante el registro de puntero especificado por la instrucción. Los registros de origen y destino pueden ser uno solo.

Actualización: El modelo de contramáquina

Melzak (1961) ofrece una visualización sencilla de una máquina contadora: sus "registros" son agujeros en el suelo, y estos agujeros contienen guijarros. Según una instrucción, dentro y fuera de estos agujeros, "la computadora" (persona o máquina) agrega (INCREMENTA) o quita (DECREMENTA) un solo guijarro. Según sea necesario, se obtienen guijarros adicionales de un suministro infinito y los guijarros sobrantes vuelven a él; si el agujero es demasiado pequeño para acomodar los guijarros, la "computadora" cava un agujero más grande.
Minsky (1961) y Hopcroft-Ullman 1979 (p. 171) ofrecen la visualización de una máquina de Turing de múltiples cintas con tantas cintas en el extremo izquierdo como "registros". La longitud de cada cinta no tiene límites hacia la derecha y todos los cuadrados están en blanco, excepto el extremo izquierdo, que está marcado. La distancia de la "cabeza" de una cinta desde su extremo izquierdo, medida en números de cuadrados de cinta, representa el número natural en "el registro". Para decrementar el número de cuadrados, la cabeza de la cinta se mueve hacia la izquierda; para incrementarla, se mueve hacia la derecha. No hay necesidad de imprimir o borrar marcas en la cinta; las únicas instrucciones condicionales son verificar si la cabeza está en el extremo izquierdo, probando una marca del extremo izquierdo con una "instrucción de salto si está marcado".
Las siguientes instrucciones "mnemónicas", por ejemplo "CLR(r)", son arbitrarias; no existe ningún estándar.

La máquina de registros tiene, como memoria externa a su máquina de estados finitos, una colección ilimitada (cf: footnote|contable e ilimitada) de ubicaciones discretas y etiquetadas de forma única con capacidad ilimitada , llamadas "registros". Estos registros contienen solo números naturales (cero y enteros positivos). Según una lista de instrucciones secuenciales en la TABLA de la máquina de estados finitos, unos pocos tipos de operaciones primitivas (por ejemplo, 2) operan sobre el contenido de estos "registros". Finalmente, está disponible una expresión condicional en forma de IF-THEN-ELSE para probar el contenido de uno o dos registros y "ramificar/saltar" la máquina de estados finitos fuera de la secuencia de instrucciones predeterminada.

Modelo base 1 : El modelo más cercano a la visualización de Minsky (1961) y a Lambek (1961):

Modelo base 2 : El modelo "sucesor" (llamado así por la función sucesora de los axiomas de Peano ):

Modelo base 3 : utilizado por Elgot-Robinson (1964) en su investigación de RASP acotados y no acotados: el modelo "sucesor" con COPIA en lugar de BORRAR:

Creación de "instrucciones de conveniencia" a partir de los conjuntos base

Los tres conjuntos básicos 1, 2 o 3 anteriores son equivalentes en el sentido de que se pueden crear las instrucciones de un conjunto utilizando las instrucciones de otro conjunto (un ejercicio interesante: una pista de Minsky (1967): declare un registro reservado, por ejemplo, llámelo "0" (o Z para "cero" o E para "borrar") para que contenga el número 0). La elección del modelo dependerá de cuál le resulte más fácil de usar al autor en una demostración, una prueba, etc.

Además, a partir de los conjuntos base 1, 2 o 3 podemos crear cualquiera de las funciones recursivas primitivas (cf Minsky (1967), Boolos-Burgess-Jeffrey (2002)). (Cómo ampliar la red para capturar las funciones recursivas mu totales y parciales se discutirá en el contexto del direccionamiento indirecto). Sin embargo, construir las funciones recursivas primitivas es difícil porque los conjuntos de instrucciones son tan... primitivos (pequeños). Una solución es expandir un conjunto particular con "instrucciones de conveniencia" de otro conjunto:

No serán subrutinas en el sentido convencional, sino más bien bloques de instrucciones creadas a partir del conjunto base y a las que se les asigna una mnemotecnia. En un sentido formal, para utilizar estos bloques necesitamos (i) "expandirlos" a sus equivalentes de instrucción base (requerirán el uso de registros temporales o "auxiliares", por lo que el modelo debe tener esto en cuenta) o (ii) diseñar nuestras máquinas/modelos con las instrucciones "integradas".
Ejemplo: Conjunto base 1. Para crear CLR (r), utilice el bloque de instrucciones para contar el registro r hasta cero. Observe el uso de la sugerencia mencionada anteriormente:
  • CLR (r) = equivalente
  • bucle : JZ (r, salida )
  • Diez (r)
  • JZ (0, bucle )
  • salida : etc.

Nuevamente, todo esto es sólo para conveniencia; nada de esto aumenta el poder intrínseco del modelo.

Por ejemplo: el conjunto más expandido incluiría cada instrucción única de los tres conjuntos, más el salto incondicional J (z), es decir:

La mayoría de los autores eligen uno u otro de los saltos condicionales, por ejemplo, Shepherdson-Sturgis (1963) utiliza el conjunto anterior menos JE (para ser perfectamente precisos, utilizan JNZ – Jump if Not Zero en lugar de JZ; otra posible instrucción de conveniencia).

La operación "indirecta"

Ejemplo de direccionamiento indirecto

En nuestra vida cotidiana el concepto de “operación indirecta” no es inusual.

Ejemplo: Una búsqueda del tesoro.
En la ubicación "Tom_&_Becky's_cave_in_pirate_chest" será donde podremos encontrar un mapa que nos dirigirá al "tesoro":
(1) Vamos a la ubicación "La cueva de Tom_&_Becky..." y excavamos hasta encontrar una caja de madera.
(2) Dentro de la caja hay un mapa que lleva a la ubicación del tesoro: "bajo el porche delantero de Thatcher".
(3) Vamos al lugar "bajo el porche delantero de Thatcher", rompemos el concreto con un martillo neumático y descubrimos "el tesoro": un saco de pomos de puertas oxidados.

La indirección especifica una ubicación identificada como el cofre pirata en "La cueva de Tom_&_Becky..." que actúa como un indicador a cualquier otra ubicación (incluida ella misma): su contenido (el mapa del tesoro) proporciona la "dirección" de la ubicación objetivo "bajo el porche delantero de Thatcher" donde ocurre la acción real.

Por qué es necesaria una operación indirecta: Dos problemas importantes del modelo de contramáquina

En lo que sigue, hay que recordar que estos modelos son modelos abstractos con dos diferencias fundamentales con respecto a cualquier cosa físicamente real: un número ilimitado de registros, cada uno con capacidades ilimitadas. El problema aparece de forma más dramática cuando se intenta utilizar un modelo de contramáquina para construir un RASP que sea equivalente a Turing y, por lo tanto, calcular cualquier función recursiva mu parcial :

Cook y Reckhow (1973) lo expresan de la manera más sucinta:
Las instrucciones indirectas son necesarias para que un programa fijo pueda acceder a un número ilimitado de registros a medida que varían las entradas". (p. 73)
A veces, la constante k se creará mediante el uso de CLR ( r ) seguido de INC ( r ) repetido k veces; por ejemplo, para poner la constante k = 3 en el registro r, es decir, 3 → r, por lo que al final de la instrucción [r] = 3: CLR (r), INC (r), INC (r), INC (r). Este truco lo menciona Kleene (1952) pág. 223. El problema surge cuando el número a crear agota el número de instrucciones disponibles para la máquina de estados finitos ; siempre hay una constante mayor que el número de instrucciones disponibles para la máquina de estados finitos .
Observe que la máquina de estados finitos de la máquina contadora debe llamar a un registro explícitamente (directamente) por su nombre/número: INC (65,356) llama explícitamente al registro número "65,365" . Si la cantidad de registros excede la capacidad de la máquina de estados finitos para acceder a ellos, entonces los registros fuera de los límites serán inalcanzables. Por ejemplo, si la máquina de estados finitos solo puede alcanzar 65,536 = 2 16 registros, entonces ¿cómo puede alcanzar el 65,537?

¿Cómo podemos entonces abordar un registro que se encuentra más allá de los límites de la máquina de estados finitos? Un enfoque sería modificar las instrucciones del programa (las almacenadas en los registros) para que contengan más de un comando. Pero esto también puede agotarse a menos que una instrucción sea de tamaño (potencialmente) ilimitado. Entonces, ¿por qué no utilizar una sola "superinstrucción" (un número realmente muy grande) que contenga todas las instrucciones del programa codificadas en él? Así es como Minsky resuelve el problema, pero la numeración de Gödel que utiliza representa un gran inconveniente para el modelo, y el resultado no se parece en nada a nuestra noción intuitiva de una "computadora con programa almacenado".

Elgot y Robinson (1964) llegan a una conclusión similar con respecto a un RASP que está "finitamente determinado". De hecho, puede acceder a un número ilimitado de registros (por ejemplo, para obtener instrucciones de ellos), pero sólo si el RASP permite la "automodificación" de las instrucciones de su programa y ha codificado sus "datos" en un número de Gödel (Fig. 2, pág. 396).

En el contexto de un modelo más parecido al de una computadora, utilizando su instrucción RPT (repetir), Minsky (1967) nos tienta con una solución al problema (cf. p. 214, p. 259) pero no ofrece una resolución firme. Afirma:

"En general, una operación RPT no podría ser una instrucción en la parte de estados finitos de la máquina... esto podría agotar cualquier cantidad particular de almacenamiento permitida en la parte finita de la computadora [sic, su nombre para sus modelos de RAM]. Las operaciones RPT requieren infinitos registros propios". (p. 214).

Nos ofrece una RPT acotada que junto con CLR (r) e INC (r) puede calcular cualquier función recursiva primitiva , y ofrece la RPT ilimitada citada anteriormente que desempeña el papel del operador μ; junto con CLR (r) e INC (r) puede calcular las funciones recursivas mu. Pero no analiza la "indirección" ni el modelo RAM en sí.

De las referencias de Hartmanis (1971) se desprende que Cook (en sus notas de clase en la Universidad de California en Berkeley, 1970) ha reafirmado la noción de direccionamiento indirecto. Esto se hace más claro en el artículo de Cook y Reckhow (1973) –Cook es el director de tesis de maestría de Reckhow. El modelo de Hartmanis –bastante similar al modelo de Melzak (1961)– utiliza sumas y restas de dos y tres registros y dos copias de parámetros; el modelo de Cook y Reckhow reduce el número de parámetros (registros llamados en las instrucciones del programa) a una llamada mediante el uso de un acumulador "AC".

La solución en pocas palabras: Diseñar nuestra máquina/modelo con indirección ilimitada  – proporcionar un registro de "dirección" ilimitado que potencialmente pueda nombrar (llamar) cualquier registro sin importar cuántos haya. Para que esto funcione, en general, el registro ilimitado requiere una capacidad de ser borrado y luego incrementado (y, posiblemente, decrementado) por un bucle potencialmente infinito. En este sentido, la solución representa el operador μ ilimitado que puede, si es necesario, buscar ad infinitum a lo largo de la cadena ilimitada de registros hasta que encuentre lo que está buscando. El registro puntero es exactamente como cualquier otro registro con una excepción: bajo las circunstancias llamadas "direccionamiento indirecto" proporciona su contenido, en lugar del operando de dirección en la TABLA de la máquina de estados, para ser la dirección del registro de destino (¡incluso posiblemente él mismo!).

Indirección acotada y funciones recursivas primitivas

Si evitamos el enfoque de Minsky de un número monstruoso en un registro y especificamos que nuestro modelo de máquina será "como una computadora", tenemos que enfrentar este problema de indirección si queremos calcular las funciones recursivas (también llamadas funciones μ-recursivas ), tanto las variedades totales como las parciales.

Nuestro modelo de contramáquina más simple puede realizar una forma "limitada" de indirección -y, por lo tanto, calcular la subclase de funciones recursivas primitivas-  utilizando un "operador" recursivo primitivo llamado "definición por casos" (definido en Kleene (1952) p. 229 y Boolos-Burgess-Jeffrey p. 74). Tal "indirección limitada" es una tarea laboriosa y tediosa. La "definición por casos" requiere que la máquina determine/distinga el contenido del registro de puntero intentando, una y otra vez hasta tener éxito, hacer coincidir este contenido con un número/nombre que el operador de caso declara explícitamente . Por lo tanto, la definición por casos comienza, por ejemplo, desde la dirección del límite inferior y continúa hasta la saciedad hacia la dirección del límite superior intentando hacer una coincidencia:

¿El número en el registro N es igual a 0? Si no, ¿es igual a 1? ¿2? ¿3? ... ¿65364? Si no, estamos en el último número 65365 y más vale que sea este, ¡de lo contrario tenemos un problema!

La indirección "acotada" no nos permitirá calcular las funciones recursivas parciales; para ellas necesitamos una indirección ilimitada , también conocida como el operador μ .

Supongamos que hubiéramos podido continuar hasta el número 65367 y que, de hecho, ese registro tenía lo que buscábamos. ¡Entonces podríamos haber completado nuestro cálculo con éxito! Pero supongamos que 65367 no tenía lo que necesitábamos. ¿Hasta dónde deberíamos continuar?

Para ser equivalente a Turing, la máquina contadora necesita utilizar el desafortunado método de número de Minsky-Gödel de un solo registro , o ser aumentada con una capacidad para explorar los extremos de su cadena de registros, ad infinitum si es necesario. (El hecho de no encontrar algo "ahí afuera" define lo que significa que un algoritmo no pueda terminar; cf. Kleene (1952) pp. 316ff Capítulo XII Funciones recursivas parciales , en particular pp. 323-325.) Vea más sobre esto en el ejemplo a continuación.

Indirección ilimitada y funciones recursivas parciales

Para que la indirección sea ilimitada , necesitamos un cambio de "hardware" en nuestro modelo de máquina. Una vez que realizamos este cambio, el modelo ya no es una máquina contadora, sino una máquina de acceso aleatorio.

Ahora bien, cuando se especifica, por ejemplo, INC, la instrucción de la máquina de estados finitos tendrá que especificar de dónde procederá la dirección del registro de interés. Este dónde puede ser (i) la instrucción de la máquina de estados que proporciona una etiqueta explícita , o (ii) el registro puntero cuyo contenido es la dirección de interés. Siempre que una instrucción especifique una dirección de registro, también deberá especificar un parámetro adicional "i/d" (indirecto/directo). En cierto sentido, este nuevo parámetro "i/d" es un "interruptor" que se activa en un sentido para obtener la dirección directa tal como se especifica en la instrucción o en el otro sentido para obtener la dirección indirecta del registro puntero (el registro puntero (en algunos modelos, cada registro puede ser un registro puntero) se especifica en la instrucción). Esta "elección mutuamente excluyente pero exhaustiva" es otro ejemplo de "definición por casos", y el equivalente aritmético que se muestra en el ejemplo siguiente se deriva de la definición de Kleene (1952), pág. 229.

Ejemplo: CPY ( fuente indirecta , fuente r, destino directo , destino r )
Asignamos un código para especificar el direccionamiento directo como d="0" y el direccionamiento indirecto como i="1". Entonces nuestra máquina puede determinar la dirección de origen de la siguiente manera:
i*[r s ] + (1-i)*r s
Por ejemplo, supongamos que el contenido del registro 3 es "5" (es decir, [3]=5) y el contenido del registro 4 es "2" (es decir, [4]=2):
Ejemplo: CPY ( 1, 3, 0, 4 ) = CPY ( indirecto, reg 3, directo, reg 4 )
1*[3] + 0*3 = [3] = dirección del registro de origen 5
0*[4] + 1*4 = 4 = dirección de registro de destino 4
Ejemplo: CPY ( 0, 3, 0, 4 )
0*[3] + 1*3 = 3 = dirección del registro de origen 3
0*[4] + 1*4 = 4 = dirección de registro de destino 4
Ejemplo: CPY ( 0, 3, 1, 4 )
0*[3] + 1*3 = 3 = dirección del registro de origen 3
1*[4] + 0*4 = [4] = dirección de registro de destino 2

La instrucción COPY indirecta

Probablemente la instrucción más útil de las que se han añadido es COPY. De hecho, Elgot-Robinson (1964) proporciona a sus modelos P 0 y P' 0 las instrucciones COPY, y Cook-Reckhow (1973) proporciona a su modelo basado en acumuladores sólo dos instrucciones indirectas: COPY al acumulador indirectamente, COPY desde el acumulador indirectamente.

Una plétora de instrucciones : debido a que cualquier instrucción que actúe sobre un solo registro puede ser aumentada con su "dual" indirecto (incluidos los saltos condicionales e incondicionales, cf el modelo de Elgot-Robinson), la inclusión de instrucciones indirectas duplicará el número de instrucciones de un solo parámetro/registro (por ejemplo, INC (d, r), INC (i, r)). Peor aún, cada instrucción de dos parámetros/registros tendrá 4 variedades posibles, por ejemplo:

CPY (d, r s , d, r d ) = COPIAR directamente del registro de origen directamente al registro de destino
CPY (i, r sp , d, r d ) = COPIA al registro de destino indirectamente utilizando la dirección de origen que se encuentra en el registro de puntero de origen r sp .
CPY (d, r s , i, r dp ) = COPIA el contenido del registro de origen indirectamente en el registro usando la dirección de destino que se encuentra en el registro de puntero de destino r dp .
CPY (i, r sp , i, r dp ) = COPIA indirectamente el contenido del registro de origen con dirección que se encuentra en el registro puntero de origen r sp , en el registro de destino con dirección que se encuentra en el registro puntero de destino r dp )

De manera similar, cada instrucción de tres registros que involucra dos registros de origen r s1 r s2 y un registro de destino r d dará como resultado 8 variedades, por ejemplo la adición:

[r s1 ] + [r s2 ] → r d

rendirá:

Si designamos un registro como "acumulador" (ver más abajo) y ponemos fuertes restricciones a las distintas instrucciones permitidas, podemos reducir en gran medida la plétora de operaciones directas e indirectas. Sin embargo, debemos estar seguros de que el conjunto de instrucciones reducido resultante sea suficiente y debemos ser conscientes de que la reducción se producirá a expensas de más instrucciones por operación "significativa".

El concepto de “acumulador A”

La convención histórica dedica un registro al acumulador, un "órgano aritmético" que literalmente acumula su número durante una secuencia de operaciones aritméticas:

"La primera parte de nuestro órgano aritmético... debería ser un órgano de almacenamiento paralelo que pueda recibir un número y añadirlo al que ya está en él, que también sea capaz de borrar su contenido y que pueda almacenar lo que contiene. Llamaremos a este órgano un acumulador . Es bastante convencional en principio en las máquinas de computación pasadas y presentes de los más variados tipos, por ejemplo, multiplicadores de escritorio, contadores estándar de IBM, máquinas de relé más modernas, el ENIAC" (negrita en el original: Goldstine y von Neumann, 1946; p. 98 en Bell y Newell 1971).

Sin embargo, el acumulador se realiza a expensas de más instrucciones por "operación" aritmética, en particular con respecto a las llamadas instrucciones de "lectura-modificación-escritura", como por ejemplo "Incrementar indirectamente el contenido del registro al que apunta el registro r2". "A" designa el registro "acumulador" A:

Si nos ceñimos a un nombre específico para el acumulador, por ejemplo, "A", podemos implicar el acumulador en las instrucciones, por ejemplo,

INC ( A ) = INCA

Sin embargo, cuando escribimos las instrucciones CPY sin llamar al acumulador, las instrucciones son ambiguas o deben tener parámetros vacíos:

CPY (d, r2, d, A) = CPY (d, r2, , )
CPY ( d, A, d, r2 ) = CPY ( , , d, r2)

Históricamente, lo que ha sucedido es que estas dos instrucciones CPY han recibido nombres distintivos; sin embargo, no existe ninguna convención. La tradición (por ejemplo, la computadora imaginaria MIX de Knuth (1973) ) utiliza dos nombres llamados LOAD y STORE. Aquí estamos agregando el parámetro "i/d":

LDA (d/i, rs ) = def CPY (d/i, rs , d, A)
STA ( d/i, r d ) = def CPY ( d, A, d/i, r d )

El modelo típico basado en acumulador tendrá todas sus operaciones aritméticas y constantes de dos variables (por ejemplo, ADD (A, r), SUB (A, r)) que utilizan (i) el contenido del acumulador, junto con (ii) el contenido de un registro especificado. Las operaciones de una variable (por ejemplo, INC (A), DEC (A) y CLR (A)) requieren solo el acumulador. Ambos tipos de instrucciones depositan el resultado (por ejemplo, suma, diferencia, producto, cociente o resto) en el acumulador.

Ejemplo: INCA = [A] +1 → A
Ejemplo: ADDA (r s ) = [A] + [r s ] → A
Ejemplo: MULA (r s ) = [A] * [r s ] → A

Si así lo deseamos, podemos abreviar la mnemotecnia porque al menos un registro de origen y el registro de destino es siempre el acumulador A. Así tenemos:

{ LDA (i/d, r s ), STA (i/d, r d ), CLRA, INCA, DECA, ADDA (r s ), SUBA (r s ), MULA (r s ), DIVA (r s ) , etc.)

El concepto de registro de dirección indirecta "N"

Si nuestro modelo tiene un acumulador ilimitado, ¿podemos limitar todos los demás registros? No hasta que proporcionemos al menos un registro ilimitado del cual derivamos nuestras direcciones indirectas.

El enfoque minimalista consiste en utilizar uno mismo (Schönhage lo hace).

Otro enfoque (Schönhage también lo hace) es declarar un registro específico como "registro de dirección indirecta" y confinar la indirección relativa a este registro (el modelo RAM0 de Schonhage utiliza registros A y N para instrucciones indirectas y directas). Nuevamente, nuestro nuevo registro no tiene un nombre convencional: tal vez "N" de "iNdex", o "iNdirect" o "address Number".

Para lograr la máxima flexibilidad, como hicimos para el acumulador A, consideraremos a N simplemente otro registro sujeto a incremento, decremento, borrado, prueba, copia directa, etc. Nuevamente, podemos reducir la instrucción a un solo parámetro que proporcione dirección e indirección, por ejemplo.

LDAN (i/d) = CPY (i/d, N, d, A); acumulador de carga a través del registro de dirección iN
STAN (i/d) = CPY (d, A, i/d, N). Acumulador de almacenamiento a través del registro de dirección iN

¿Por qué es este un enfoque tan interesante? Al menos por dos razones:

(1) Un conjunto de instrucciones sin parámetros:

Schönhage hace esto para producir su conjunto de instrucciones RAM0. Vea la sección a continuación.

(2) Reducir una RAM a una máquina Post-Turing:

Haciéndonos pasar por minimalistas, reducimos todos los registros, excepto el acumulador A y el registro de indirección N, p. ej. r = { r0, r1, r2, ... }, a una cadena ilimitada de casillas de capacidad (muy) limitada. Estas no harán nada más que contener números (muy) limitados, p. ej., un bit solitario con valor { 0, 1 }. Del mismo modo, reducimos el acumulador a un solo bit. Restringimos cualquier operación aritmética a los registros { A, N }, utilizamos operaciones indirectas para extraer el contenido de los registros al acumulador y escribimos 0 o 1 del acumulador en un registro:

{ LDA (i, N), STA (i, N), CLR (A/N), INC (A/N), DEC(N), JZ (A/N, I z ), JZ (I z ), H }

Vamos más allá y eliminamos A por completo mediante el uso de dos registros "constantes" llamados "ERASE" e "PRINT": [ERASE]=0, [PRINT]=1.

{ CPY (d, BORRAR, i, N), CPY (d, IMPRIMIR, i, N), CLR (N), INC (N), DEC (N), JZ (i, N, I z ), JZ (I z ), H }

Cambie el nombre de las instrucciones COPY y llame INC (N) = RIGHT, DEC (N) = LEFT y tendremos las mismas instrucciones que la máquina Post-Turing, más un CLRN adicional:

{ BORRAR, IMPRIMIR, BORRAR, DERECHA, IZQUIERDA, JZ (i, N, I z ), JZ (I z ), H }

Equivalencia de Turing de la RAM con indirección

En la sección anterior demostramos informalmente que una RAM con una capacidad de indirección ilimitada produce una máquina Post-Turing . La máquina Post-Turing es equivalente a Turing, por lo que hemos demostrado que la RAM con indirección es equivalente a Turing.

Aquí damos una demostración un poco más formal. Empecemos por diseñar nuestro modelo con tres registros reservados "E", "P" y "N", más un conjunto ilimitado de registros 1, 2, ..., n a la derecha. Los registros 1, 2, ..., n se considerarán "los cuadrados de la cinta". El registro "N" apunta al "cuadrado escaneado" que "la cabeza" está observando en ese momento. Se puede pensar que la "cabeza" está en el salto condicional; observe que utiliza direccionamiento indirecto (cf Elgot-Robinson p. 398). A medida que disminuimos o incrementamos "N", la cabeza (aparente) se "desplazará hacia la izquierda" o "hacia la derecha" a lo largo de los cuadrados. Moveremos el contenido de "E"=0 o "P"=1 al "cuadrado escaneado" al que apunta N, utilizando el CPY indirecto.

El hecho de que nuestra cinta tenga un extremo izquierdo nos presenta un problema menor: cada vez que ocurre LEFT nuestras instrucciones tendrán que probar para determinar si el contenido de "N" es cero o no; si es así, debemos dejar su conteo en "0" (esta es nuestra elección como diseñadores; por ejemplo, podríamos hacer que la máquina/modelo "dispare un evento" de nuestra elección).

Conjunto de instrucciones 1 (aumentado): { INC (N), DEC (N), CLR (N), CPY (d, r s ,i, N), JZ ( i, r, z ), HALT }

La siguiente tabla define las instrucciones Post-Turing en términos de sus instrucciones equivalentes en RAM y ofrece un ejemplo de su funcionamiento. La ubicación (aparente) del cabezal a lo largo de la cinta de registros r0-r5 . . . se muestra sombreada:

Ejemplo: La indirección acotada produce una máquina que no es equivalente a Turing

A lo largo de esta demostración debemos tener en cuenta que las instrucciones en la TABLA de la máquina de estados finitos están acotadas , es decir, son finitas :

"Además de ser simplemente un conjunto finito de reglas que proporciona una secuencia de operaciones para resolver un tipo específico de problema, un algoritmo tiene cinco características importantes [Finitud, Definición, Entrada, Salida, Efectividad]" (cursiva añadida, Knuth p. 4-7).
La dificultad surge porque los registros tienen "nombres" explícitos (números) y nuestra máquina debe llamar a cada uno por su nombre para poder "acceder" a él.

Construiremos el CPY indirecto (i, q, d, φ) con el operador CASE. La dirección del registro de destino se especificará mediante el contenido del registro "q"; una vez que el operador CASE haya determinado cuál es este número, CPY depositará directamente el contenido del registro con ese número en el registro "φ". Necesitaremos un registro adicional que llamaremos "y" - sirve como contador ascendente.

Por lo tanto, lo que sigue es en realidad una demostración o prueba constructiva de que podemos simular el CPY indirecto (i, q, d, φ) sin un cambio de diseño de "hardware" en nuestra máquina/modelo de contador. Sin embargo, tenga en cuenta que debido a que este CPY indirecto está "limitado" por el tamaño/extensión de la máquina de estados finitos, un RASP que utilice este CPY indirecto solo puede calcular las funciones recursivas primitivas , no el conjunto completo de funciones recursivas mu .

El "operador" CASE se describe en Kleene (1952) (p. 229) y en Boolos-Burgess-Jeffrey (2002) (p. 74); estos últimos autores destacan su utilidad. La siguiente definición es de Kleene, pero modificada para reflejar la conocida construcción "IF-THEN-ELSE".

El operador CASE "devuelve" un número natural en φ dependiendo de qué "caso" se satisface, comenzando con "case_0" y pasando sucesivamente por "case_last"; si no se satisface ningún caso, entonces el número llamado "predeterminado" (también conocido como "woops") se devuelve en φ (aquí x designa alguna selección de parámetros, por ejemplo, el registro q y la cadena r0, ... rlast )):

Definición por casos φ ( x , y):

  • case_0: SI Q 0 ( x , y) es verdadero ENTONCES φ 0 ( x , y) DE LO CONTRARIO
  • caso_1: SI Q 1 ( x , y) es verdadero ENTONCES φ 1 ( x , y) DE LO CONTRARIO
  • casos_2 a caso_anterior_al_último: etc. . . . . . . . . DE LO CONTRARIO
  • case_last: SI Q last ( x , y) es verdadero ENTONCES φ last ( x , y) DE LO CONTRARIO
  • predeterminado: hacer φ predeterminado ( x , y)

Kleene requiere que los "predicados" Q n que realizan las pruebas sean todos mutuamente excluyentes – los "predicados" son funciones que producen solo { verdadero, falso } como salida; Boolos-Burgess-Jeffrey agregan el requisito de que los casos sean "exhaustivos".

Comenzamos con un número en el registro q que representa la dirección del registro de destino. Pero, ¿qué es este número? Los "predicados" lo probarán para averiguarlo, un ensayo tras otro: JE (q, y, z) seguido de INC (y). Una vez identificado explícitamente el número, el operador CASE copia directa/explícitamente el contenido de este registro a φ:

Definición por casos CPY (i, q, d, φ) = def φ (q, r0, ..., rlast, y) =
  • caso_0: SI CLR (y), [q] - [y]=0 ENTONCES CPY ( r0, φ ), J (salir) DE LO CONTRARIO
  • caso_1: SI INC (y), [q] = [y]=1 ENTONCES CPY ( r1, φ ), J (salir) DE LO CONTRARIO
  • caso_2 hasta caso n: SI . . . ENTONCES . . . DE LO CONTRARIO
  • case_n: SI INC (y), [q] = [y]=n ENTONCES CPY ( rn, φ ), J (salir) DE LO CONTRARIO
  • caso_n+1 a caso_último: SI . . . ENTONCES . . . DE LO CONTRARIO
  • case_last: SI INC (y), [q] = [y]="último" ENTONCES CPY ( rlast, φ ), J (salir) DE LO CONTRARIO
  • predeterminado: woops

El caso_0 (el paso base de la recursión en y) se ve así:

  • caso_0 :
  • CLR ( y ); establecer registro y = 0
  • JE ( q, y, _φ0 )
  • J ( caso_1 )
  • _φ0: CPY ( r0, φ )
  • J ( salir )
  • caso_1: etc.

El caso_n (el paso de inducción) se ve así; recuerde, cada instancia de "n", "n+1", ..., "último" debe ser un número natural explícito:

  • caso_n :
  • INC ( y )
  • JE ( q, y, _φn )
  • J ( caso_n+1 )
  • _φn: CPY ( rn, φ )
  • J ( salir )
  • caso__n+1: etc.

Case_last detiene la inducción y limita el operador CASE (y por lo tanto limita el operador de "copia indirecta"):

  • caso_último :
  • INC ( y )
  • JE ( q, y, _φlast )
  • J ( ups )
  • _φlast : CPY ( rlast, φ )
  • J ( salir )
  • Ups: ¿Cómo manejamos un intento fuera de los límites del campo?
  • salida: etc.

Si el CASE pudiera continuar hasta el infinito, sería el operador mu . Pero no puede: el "registro de estado" de su máquina de estados finitos ha alcanzado su recuento máximo (por ejemplo, 65365 = 11111111,11111111 2 ) o su tabla se ha quedado sin instrucciones; después de todo, es una máquina finita .

Ejemplos de modelos

Modelo de registro a registro ("lectura-modificación-escritura") de Cook y Reckhow (1973)

El modelo de Cook y Rechkow, tan común, es un poco como el modelo Malzek de registro ternario (escrito con mnemotecnia Knuth; las instrucciones originales no tenían mnemotecnia excepto TRA, Leer, Imprimir).

  • LOAD ( C, rd ) ; C → rd, C es cualquier entero
Ejemplo: LOAD ( 0, 5 )borrará el registro 5.
  • ADD ( rs1, rs2, rd ) ; [rs1] + [rs2] → rd, los registros pueden ser iguales o diferentes;
Ejemplo: ADD ( A, A, A )duplicará el contenido del registro A.
  • SUB ( rs1, rs2, rd ) ; [rs1] - [rs2] → rd, los registros pueden ser iguales o diferentes:
Ejemplo: SUB ( 3, 3, 3 )borrará el registro 3.
  • COPY ( i, rp, d, rd ) ; [[rp] ] → rd, Copia indirectamente el contenido del registro de origen señalado por el registro puntero r p en el registro de destino.
  • COPY ( d, rs, i, rp ) ; [rs] → [rp]. Copiar el contenido del registro de origen r s en el registro de destino señalado por el registro puntero r p .
  • JNZ ( r, Iz ) ;Salto condicional si [r] es positivo; es decir, SI [r] > 0 ENTONCES salta a la instrucción z, de lo contrario continúa en secuencia (Cook y Reckhow llaman a esto: "Transferir el control a la línea m si Xj > 0")
  • READ ( rd ) ;Copiar "la entrada" en el registro de destino r d
  • PRINT ( rs ) ;copia el contenido del registro fuente r s a "la salida".

RAM0 y RAM1 de Schönhage (1980)

Schönhage (1980) describe un modelo atomizado muy primitivo elegido para su prueba de la equivalencia de su modelo de máquina de puntero SMM :

"Para evitar cualquier direccionamiento explícito, la RAM0 tiene el acumulador con contenido z y un registro de dirección adicional con contenido actual n (inicialmente 0)" (p. 494)

Modelo RAM1 : Schönhage demuestra cómo se puede utilizar su construcción para formar la forma más común y utilizable de RAM tipo "sucesora" (utilizando los mnemónicos de este artículo):

  • LDA k ; k --> A , k es una constante, un número explícito como "47"
  • LDA ( d, r ) ; [r] → A ;cargar directamente A
  • LDA ( i, r ) ; [[r]] → A ;cargar indirectamente A
  • STA ( d, r ) ; [A] → r ;almacenar directamente A
  • STA ( i, r ) ; [A] → [r] ;almacenar indirectamente A
  • JEA ( r, z ) ; IF [A] = [r] then Iz else continue
  • INCA ; [A] + 1 --> A

Modelo RAM0 : La máquina RAM0 de Schönhage tiene 6 instrucciones indicadas por una sola letra (la sexta "C xxx" parece implicar 'saltar el siguiente parámetro'. Schönhage designó el acumulador con "z", "N" con "n", etc. En lugar de los mnemónicos de Schönhage, utilizaremos los mnemónicos desarrollados anteriormente.

  • (Z), CLRA: 0 → A
  • (A), INCA: [A] +1 → A
  • (N), CPYAN: [A] → N
  • (A), LDAA: [[A]] → A ; el contenido de A apunta a la dirección del registro; coloque el contenido del registro en A
  • (S), STAN: [A] → [N] ; el contenido de N apunta a la dirección del registro; coloca el contenido de A en el registro apuntado por N
  • (C), JAZ ( z ): [A] = 0 then go to Iz ; ambiguo en su tratamiento

La indirección proviene (i) de CPYAN (copiar/transferir contenidos A a N) trabajando con store_A_via_N STAN, y de (ii) la peculiar instrucción de indirección LDAA ( [[A]] → [A] ).

Notas al pie

Finito vs ilimitado

El hecho definitorio de que cualquier tipo de máquina contadora sin un registro de "dirección" ilimitado debe especificar un registro "r" por nombre indica que el modelo requiere que "r" sea finito , aunque es "ilimitado" en el sentido de que el modelo no implica un límite superior para la cantidad de registros necesarios para realizar su(s) trabajo(s). Por ejemplo, no requerimos que r < 83.617.563.821.029.283.746 ni que r < 2^1.000.001, etc.

De este modo, nuestro modelo puede "expandir" el número de registros, si es necesario para realizar un determinado cálculo. Sin embargo, esto significa que cualquier número al que se expanda el modelo debe ser finito  , es decir, debe ser indexable con un número natural: ω no es una opción .

Podemos escapar de esta restricción proporcionando un registro ilimitado para proporcionar la dirección del registro que especifica una dirección indirecta.

Véase también

Enlaces externos

Referencias

  1. ^ Érdi, Gergő (6 de septiembre de 2010). "De Register Machines a Brainfuck, parte 1" . Consultado el 7 de febrero de 2024 .

Con algunas excepciones, estas referencias son las mismas que las de Register machine .

  • Kaphengst, Heinz, Eine Abstrakte programmgesteuerte Rechenmaschine' , Zeitschrift fur mathematische Logik und Grundlagen der Mathematik: 5 (1959), 366-379.
  • Ershov, AP On operator algorithms , (ruso) Dok. Akad. Nauk 122 (1958), 967-970. Traducción al inglés, Automat. Express 1 (1959), 20-23.
  • Péter, Rózsa Graphschemata und rekursive Funktionen , Dialectica 12 (1958), 373.
  • Hermes, Hans Die Universalität programmgesteuerter Rechenmaschinen. Matemáticas-Física. Semsterberichte (Gotinga) 4 (1954), 42-53.