¿Son intercambiables todos los idiomas completos?


26

Tenga en cuenta que, aunque sé programar, soy un principiante en la teoría de CS.

De acuerdo con esta respuesta

La integridad de Turing es un concepto abstracto de computabilidad. Si un idioma es completo de Turing, entonces es capaz de hacer cualquier cálculo que cualquier otro lenguaje completo de Turing puede hacer.

Y cualquier programa escrito en cualquier idioma completo de Turing puede reescribirse en otro .

Okay. Esto tiene sentido. Puedo traducir (compilar) C en ensamblaje (¡y lo hago todos los días!), Y puedo traducir ensamblar en C (puede escribir una máquina virtual en C). Y lo mismo se aplica a cualquier otro idioma: puede compilar cualquier idioma en ensamblador y luego ejecutarlo en una máquina virtual escrita en otro idioma.

¿Pero puede algún programa escrito en un lenguaje completo de Turing ser reescrito en otro?

¿Qué sucede si mi Asamblea tiene un código de operación LIGHTBUTTON? Físicamente no puedo emular ese idioma en un sistema (idioma) sin una bombilla.

Okay. Entonces dirá que, dado que estamos tratando con la teoría de la computadora , no estamos discutiendo las limitaciones del dispositivo físico.

Pero, ¿qué pasa con un dispositivo que no tiene multiplicación? ¿división? A lo mejor de mi conocimiento (aunque esto es más una pregunta para matemáticas. SE), uno no puede emular la multiplicación (y definitivamente no la división) con suma y resta [1].

Entonces, ¿cómo un "lenguaje completo de turing" (que puede sumar, restar y saltar) emularía otro idioma que pueda sumar, restar, multiplicar y saltar?

EDITAR

[1] En números reales arbitrarios.


33
Los números reales pertenecen al reino de la computación Hyper-Turing. Una máquina de Turing no puede manejar números reales, por lo tanto, son irrelevantes para la integridad de Turing.
Jörg W Mittag el

3
Relacionado: un conjunto de instrucciones en lenguaje ensamblador con una sola instrucción sigue siendo lo suficientemente potente como para construir una computadora universal: en.wikipedia.org/wiki/One_instruction_set_computer . Por ejemplo, "Restar y ramificar si es menor o igual que cero" con operandos de memoria. Será lento en comparación con un x86 moderno, pero la relación de rendimiento es finita para cualquier programa.
Peter Cordes

1
Ninguna máquina física (realmente existente) está o puede estar completa en Turing, porque la integridad de Turing requiere almacenamiento infinito y el universo no es infinito. De esto se deduce que la respuesta afirmativa a si dos máquinas abstractas son equivalentes no ayuda a responder la pregunta de si dos aproximaciones físicas de esas máquinas son equivalentes.
Ben

2
@PeterCordes: Supongo que cuando dices que la relación es finita, simplemente quieres decir que cualquier tarea que se complete en tiempo finito en cualquiera de los dos lo hará en tiempo finito en ambos, no eso para cualquier máquina en particular (sin incluir la entrada). cualquier límite finito a qué tan alto podría llegar el cociente para algunas entradas. Creo que se podrían construir máquinas completas de Turing para las cuales se podrían seleccionar entradas que harían la relación arbitrariamente alta, posiblemente ni siquiera una función computable del tamaño de entrada.
supercat

66
No sé de dónde sacas la idea de que "no se puede emular la multiplicación (y definitivamente no la división) con la suma y la resta". Fue enseñado desde la escuela primaria cuando aprendemos a multiplicar
phuclv

Respuestas:


55

La integridad de Turing dice una cosa y solo una cosa: un modelo de cómputo es completo de Turing, si cualquier cálculo que pueda ser modelado por una máquina de Turing también puede ser modelado por ese modelo.

Entonces, ¿cuáles son los cálculos que puede modelar una máquina de Turing? Bueno, ante todo, Alan Turing y todos sus colegas solo estaban interesados ​​en las funciones de los números naturales. Entonces, la máquina de Turing (y el cálculo λ, el cálculo del combinador SK, las funciones recursivas μ, ...) solo hablan sobre la computabilidad de las funciones en números naturales. Si no está hablando de una función en números naturales, entonces el concepto de integridad de Turing ni siquiera tiene sentido, simplemente no es aplicable.

Sin embargo, tenga en cuenta que podemos codificar muchas cosas interesantes como números naturales. Podemos codificar cadenas como números naturales, podemos codificar gráficos como números naturales, podemos codificar booleanos como números naturales. ¡Podemos codificar Máquinas de Turing como números naturales, lo que nos permite crear Máquinas de Turing que hablen de Máquinas de Turing!

Y, por supuesto, no todas las funciones en números naturales son computables. Una máquina de Turing solo puede calcular algunas funciones en números naturales, el cálculo λ solo puede calcular algunas funciones en números naturales, el cálculo del combinador SK solo puede calcular algunas funciones en números naturales, ... Sorprendentemente (o no), resulta que cada modelo de computación (que en realidad es realizable en nuestro universo físico) puede computar las mismas funciones en números naturales (al menos para todos los modelos que hemos encontrado hasta ahora). [Nota: obviamente, hay modelos de computación más débiles , pero aún no hemos encontrado uno que sea más fuerte, excepto algunos que obviamente son incompatibles con nuestro universo físico, como los modelos que usan números reales o viajes en el tiempo.]

Este hecho, que después de un largo tiempo de búsqueda de muchos modelos diferentes, encontramos, cada vez, que pueden calcular exactamente las mismas funciones, es la base de la Tesis de Turing de la Iglesia, que dice (aproximadamente) que todos Los modelos de computación son igualmente poderosos y todos ellos capturan la noción "ideal" de lo que significa ser "computable". (También hay un segundo aspecto más filosófico de la CTT, a saber, que un humano que sigue un algoritmo también puede calcular exactamente las mismas funciones que una TM puede calcular y nada más).

Sin embargo , nada de esto dice nada sobre

  • qué tan eficientes son los distintos modelos
  • qué tan convenientes son para usar
  • qué más pueden hacer además de calcular funciones en los números naturales

Y ahí es precisamente donde entran en juego las diferencias entre los diferentes modelos de computación (y lenguajes de programación).

Como ejemplo de rendimiento diferente, tanto una máquina de acceso aleatorio como una máquina de Turing pueden copiar una matriz. Pero, una RAM necesita para hacer eso, mientras que un TM necesita , ya que necesita omitir los elementos de la matriz para copiar cada elemento , y hay elementos para copiar.O(sizearray)O(sizearray2)sizearraysizearray

Como ejemplo para una conveniencia diferente, puede comparar el código escrito en un lenguaje de muy alto nivel, el código escrito en ensamblador y la descripción de un TM para resolver el mismo problema.

Y su interruptor de luz es un ejemplo del tercer tipo de diferencia, cosas que algunos modelos pueden hacer que no son funciones en números naturales y, por lo tanto, no tienen nada que ver con la integridad de Turing.

Para responder a sus preguntas específicas:

¿Pero puede algún programa escrito en un lenguaje completo de Turing ser reescrito en otro?

No. Solo si el programa calcula una función computable de Turing en números naturales. E incluso entonces, podría necesitar una codificación compleja. Por ejemplo, el cálculo λ ni siquiera tiene números naturales, deben codificarse utilizando funciones (porque las funciones son lo único que tiene el cálculo λ).

Esta codificación de la entrada y la salida puede ser muy compleja, al igual que expresar el algoritmo. Entonces, si bien es cierto que cualquier programa puede reescribirse, el programa reescrito puede ser mucho más complejo, mucho más grande, usar mucha más memoria y ser mucho más lento.

¿Qué sucede si mi Asamblea tiene un código de operación LIGHTBUTTON? Físicamente no puedo emular ese idioma en un sistema (idioma) sin una bombilla.

Una bombilla no es una función computable de Turing en números naturales. Realmente, una bombilla no es ni una función ni un cálculo. Encender y apagar una bombilla es un efecto secundario de E / S. Las máquinas de Turing no modelan los efectos secundarios de E / S, y Turing-completo no es relevante para ellos.

En números reales arbitrarios.

La integridad de Turing solo se ocupa de funciones computables en números naturales, no se ocupa de números reales.

La integridad de Turing simplemente no es muy interesante cuando se trata de preguntas como la suya por dos razones:

  1. No es un obstáculo muy alto. Todo lo que necesita es IF, GOTO, WHILE, y una variable único entero (suponiendo que la variable puede contener arbitrariamente grandes números enteros). O recursión. Montones, montones y montones de cosas es completo de Turing. El juego de cartas Magic: The Gathering está completo. CSS3 es Turing completo. El sendmailarchivo de configuración es Turing completo. El Intel x86 MMU es Turing completo. La MOVinstrucción Intel x86 es completa de Turing. Las animaciones de PowerPoint son Turing-complete. Excel (sin secuencias de comandos, solo con fórmulas) es Turing-complete. El protocolo de enrutamiento BGP es Turing completo. sedestá Turing completo. Las mod_rewritereglas de Apache son Turing-complete. Google para " (accidental o sorprendentemente) turing completo"para encontrar otros ejemplos interesantes. Si casi todo es Turing-complete, ser Turing-complete deja de ser una propiedad interesante.
  2. En realidad no es necesario ser útil. Muchas cosas útiles no son completas para Turing. CSS antes de la versión 3 no es Turing completo (y el hecho de que CSS3 es en realidad no es utilizado por nadie). SQL antes de 1999 no estaba completo de Turing, sin embargo, fue tremendamente útil incluso entonces. El lenguaje de programación C sin bibliotecas adicionales no parece ser Turing completo . Los lenguajes de tipo dependiente son, más o menos por definición, no completos de Turing, sin embargo, puede escribir sistemas operativos, servidores web y juegos en ellos.

Edwin Brady, el autor de Idris, usa el término "Tetris-complete" para hablar sobre algunos de estos aspectos. Estar Tetris completo no está rigurosamente definido (aparte del obvio "se puede usar para implementar Tetris"), pero abarca cosas como ser lo suficientemente alto y expresivo como para poder escribir un juego sin volverse loco, ser capaz de interactuar con el mundo exterior (entrada y salida), ser capaz de expresar efectos secundarios, ser capaz de escribir un bucle de eventos, ser capaz de expresar programación reactiva, asíncrona y concurrente, ser capaz de interactuar con el sistema operativo, ser capaz de para interactuar con bibliotecas extranjeras (en otras palabras: poder llamar y ser llamado por código C) y así sucesivamente. Esas son características mucho más interesantes de un lenguaje de programación de propósito general que la integridad de Turing.


Puede encontrar interesante mi respuesta a la pregunta que ha vinculado , que toca algunos de los mismos puntos aunque responda una pregunta diferente.


77
Realmente me gusta esta respuesta, pero creo que vale la pena señalar que podemos representar todo tipo de cosas interesantes por números naturales. Por ejemplo, podemos representar cadenas por números naturales, podemos representar gráficos por números naturales, podemos representar todo el estado de la memoria de una computadora por un número natural. Los números reales pueden codificarse como funciones en números naturales y (muchas) funciones en números naturales pueden codificarse por números naturales. Por lo tanto, limitar las funciones de números naturales a números naturales no es una gran limitación, a menos que esté oscuro y desee que su computadora encienda la luz.
Theodore Norvell

3
Buena respuesta, pero esto: "estar completo de Turing deja de ser una propiedad interesante" es simplemente incorrecto. Si algo es Turing completo, entonces su problema de detención es Turing completo por reducción computable al problema de detención para máquinas Turing. Por ejemplo, el juego de cartas Magic: The Gathering está completo en Turing. Esto significa que sus reglas son indecidibles , es decir, en el caso general, es imposible deducir de manera computable cuál será el siguiente estado del juego, que es una propiedad muy interesante. Más en serio, usamos Turing-completeness y reducciones para probar problemas indecidibles.
Quicksort el

Turing y sus colegas estaban interesados ​​en las funciones de los números naturales, pero las máquinas de Turing en realidad no tratan con números, sino con cadenas de símbolos. Obviamente, puede interpretar trivialmente las líneas finitas de símbolos en un alfabeto finito conocido como números naturales, pero los TM no hacen directamente cosas "numéricas" con su entrada, simplemente manipulan los "dígitos". Realmente necesita un poco de lógica para pasar de las descripciones estándar de TM a "funciones en números naturales"; Al trabajar con TM, codifica los números naturales como cadenas, no las cadenas como números.
Ben

Obviamente, esta es una gran respuesta, pero me temo que va más allá de la comprensión de OP. OP ya está confundido acerca de implementar la multiplicación en (subconjuntos finitos de) números reales. Dado esto, su respuesta parece implicar que los lenguajes de programación completos de Turing no son, de hecho, intercambiables con fines de computación pura, cuando en realidad lo son (porque todo lo que hacen las CPU modernas, no solo algunas cosas) puede codificarse como natural números).
Konrad Rudolph el

99
@TheodoreNorvell Sobre el tema de codificar números reales con números naturales. De hecho, casi todos los números reales no pueden ser codificados por números naturales. El conjunto de números reales que pueden codificarse por números naturales, en virtud de estar codificados por números naturales, es como mucho infinitamente contable. Y debido a que solo es contablemente infinito, el conjunto tiene una medida cero. Es un poco falso decir que podemos representar números reales en general con números naturales, ya que solo podemos representar una fracción infinitesimal de ellos, o para ser más precisos: 0%.
Shufflepants

9

Por supuesto, puede implementar la multiplicación con suma y resta:

/* Assume b is positive for simplicity */
int multiply(int a, int b) {
  int res = 0;
  while (b > 0) { res += a; b -= 1; }
  return res;
}

El hecho de que probablemente no haría eso no lo hace menos posible.

La división es apenas más difícil:

/* Assume a and b are positive for simplicity */
int divide(int a, int b) {
  int res = 0;
  while (a >= b) { res += 1; a -= b; }
  return res;
}

¿Y cómo crees que la multiplicación y la división se realizan realmente en los circuitos de la CPU? Sugerencia: no es una tabla de búsqueda enorme. Es más eficiente que lo anterior, ya que también se usa el desplazamiento de bits, pero se implementa fundamentalmente en términos de suma y resta.


44
@touring: funciona bien para coma flotante. Primero, normaliza las mantisas para que el numerador tenga ceros binarios finales. Entonces haces división entera. Finalmente arreglas el exponente: diferencia de los exponentes originales más la corrección de la normalización. 2precision
rici

77
@touring: Sabes, la aritmética de coma flotante estaba disponible antes de que hubiera coprocesadores de coma flotante.
rici

6

Ninguna máquina física (realmente existente) está o puede estar completa en Turing, porque la integridad de Turing requiere almacenamiento infinito y el universo no es infinito.

De esto se deduce que la respuesta afirmativa a si dos máquinas abstractas son equivalentes no ayuda a responder la pregunta de si dos aproximaciones físicas de esas máquinas son equivalentes.

Por lo tanto, la equivalencia de Turing de los modelos abstractos de (por ejemplo) dos idiomas no significa que cada uno pueda calcular todo lo que el otro puede calcular en la práctica. Uno puede encontrarse con limitaciones físicas antes que el otro.


Pero la pregunta fue sobre los idiomas. Menciona máquinas particulares, pero solo porque no se da cuenta de que prácticamente ninguna máquina real funciona con números reales.
Shufflepants

3

Se podría aplicar la multiplicación y división como adición repetida y la resta, respectivamente, observando que y .m / n = 1 + ( m - n ) / nnm=n+n(m1)m/n=1+(mn)/n

De hecho, las operaciones "sumar 1", "restar 1" y "salto condicional si un registro especificado es cero" son suficientes para hacer que un modelo computacional sea Turing completo (ver la máquina de 2 contadores como referencia para un modelo computacional completo de Turing muy mínimo).

También es posible implementarlos de una manera que conserve la complejidad computacional. En primer lugar, observe que la multiplicación por es "libre" ( ). Usando la multiplicación por , el bucle y la resta, podemos implementar fácilmente el algoritmo euclidiano para la división por dos. Con la multiplicación y división por dos, podemos implementar el algoritmo ruso para la multiplicación, observando que y . Con la multiplicación arbitraria, finalmente podemos implementar el algoritmo euclidiano completo para la división.2 n = n + n 2 m × 2 n = 2 m × n m × ( 2 n + 1 ) = m + 2 m × n22n=n+n2m×2n=2m×nm×(2n+1)=m+2m×n


3

tl; dr : las máquinas de Turing son solo una descripción lógica básica para el funcionamiento de un sistema lógico general. Pueden hacer la mayoría de las cosas que podemos describir, incluyendo llamar a códigos de operación especializados y operaciones matemáticas construidas.


¿Qué sucede si mi Asamblea tiene un código de operación LIGHTBUTTON? Físicamente no puedo emular ese idioma en un sistema (idioma) sin una bombilla.

En un modelo de Turing, los símbolos como un LIGHTBUTTONcódigo de operación son solo cadenas en cualquier alfabeto que use la computadora de Turing.

Entonces, la máquina Turing sería responsable de producir la cadena "LIGHTBUTTON", o algún valor entero que corresponda a ese código de operación; si una entidad externa actúa o no, no es asunto de la computadora Turing.

Los programas C tienen la misma limitación. Esto es, un programa en C solo puede llamar al código de operación LIGHTBUTTON, sin embargo si la CPU realmente realiza o no una operación asociada con ese código de operación depende de la CPU.


Pero, ¿qué pasa con un dispositivo que no tiene multiplicación? ¿división? A lo mejor de mi conocimiento (aunque esto es más una pregunta para matemáticas. SE), uno no puede emular la multiplicación (y definitivamente no la división) con suma y resta [en números reales arbitrarios].

Sí, una máquina de Turing podría hacer esas cosas, incluso en números reales, en la medida en que cualquier lógica descriptiva por humanos podría hacerlo. La máquina de Turing podría ser tan simple como una automatización celular de la Regla 110 .

El truco es construir un sistema lógico a partir de cualquier física que la máquina tenga naturalmente. Por ejemplo, las CPU convencionales pueden multiplicar y dividir porque tienen una unidad lógica aritmética (ALU) . Pero los ALU no son mágicos; son simplemente puertas lógicas simples . Y esas puertas lógicas están hechas de transistores . Y esos transistores están hechos de arena dopada .

Entonces, para obtener un dispositivo completo de Turing para hacer matemáticas, solo tengo que programarlo de esa manera.

ππ=0ππππ=0


3

¿Pero puede algún programa escrito en un lenguaje completo de Turing ser reescrito en otro?

Si la entrada al programa es una secuencia de bits arbitrariamente larga y la salida también es una secuencia de bits arbitrariamente larga, entonces SÍ. Suponiendo que tiene el tiempo y la energía para reescribirlo, y que no le importa el rendimiento, y que tiene suficiente memoria física para ambas implementaciones.

Las consideraciones prácticas que significan que dos idiomas completos de Turing no son intercambiables incluyen:

  • admiten diferentes tipos de entrada y salida (por ejemplo, acceso a bases de datos SQL)

  • tienen diferentes bibliotecas de tipos de datos (por ejemplo, soporte para cadenas Unicode)

  • Proporcionan diferentes paradigmas de programación optimizados para diferentes tareas (por ejemplo, objetos, subprocesos, corutinas, funciones de primera clase)

  • Proporcionan diferentes bibliotecas de funciones (por ejemplo, análisis y serialización XML)


1

No. La integridad de Turing no tiene nada que ver con los programas , se trata de funciones matemáticas (o algoritmos ). Cualquier algoritmo, cualquier cálculo , puede hacerlo en C, puede hacerlo en cualquier otro lenguaje completo de Turing (esto debería ser obvio). Pero la integridad de Turing en realidad no dice que pueda hacer E / S, en absoluto. No habla del hardware en absoluto. Solo los cálculos.

Puede extender un lenguaje completo de Turing con cualquier operación de hardware que desee (técnicamente, así es fputcy cómo fgetcfunciona en C). Si toma dos idiomas completos de Turing y los extiende con operaciones idénticas específicas de hardware, entonces permanecen intercambiables. Por lo tanto, su lenguaje ensamblador con LIGHTBULBoperación es más poderoso que Turing-complete; se podría decir que se ha terminado TuringLIGHTBULB . Para hacer que cualquier otro idioma sea idéntico al mismo, también debe completarse Turing LIGHTBULB; la forma más fácil de hacerlo es agregarle una LIGHTBULBprimitiva / instrucción / función / etc.

Esta es la razón por la cual las implementaciones de C generalmente admiten ensamblador en línea o documentan una forma de llamar a funciones escritas en ensamblador, y por qué las implementaciones de otros lenguajes generalmente proporcionan una forma de llamar a funciones escritas en C.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.