Autor Tema: Comentarios a "La Aritmética Recursiva Primitiva"

0 Usuarios y 1 Visitante están viendo este tema.

10 Junio, 2023, 12:12 pm
Respuesta #30

Carlos Ivorra

  • Administrador
  • Mensajes: 11,883
  • País: es
  • Karma: +0/-0
  • Sexo: Masculino
    • Página web personal
Y bueno, con la computadora imaginaria siempre es todo más fácil.  :P

Sí, tras postear mi mensaje me dí cuenta que podía haber nombrado la máquina de Turing,
pero no agregué ninguna aclaración, y además no es una máquina real.
Es un mecanismo imaginario, más complicado que lo que se está queriendo representar con eso.

La última frase no la entiendo: dices que una máquina de Turing es más complicada que ¿qué cosa? Porque diría que estás diciendo que es más complicada que ella misma, así que no he entendido a qué hacías referencia.

Discusión aparte, para mí, la estructura de la cinta de la máquina de Turing es la que mejor refleja la estructura mental subyacente de los números naturales.
Esa estructura "espacial" (que mantiene "pegado", "conectado", cada casillero con su siguiente y también con el anterior) me da una imagen más nítida del pensamiento secuencial necesario para concebir los naturales.
Salvo los duendes del cuento del Argentinator feliz, lo demás me funciona mejor que cualquier otra "sucesión" que pretenda ser la de naturales.

Insisto que el cuento del Argentinator feliz es muy ilustrativo y es perfecto para que puedas llegar a la conclusión de que el problema no existe. No hay diferencia práctica entre una cinta que está toda ahí, con sus infinitas casillas o una cinta a la que se le van añadiendo casillas (o los signos impresos que debe haber en ella) a medida que avanzas por ella (ni habría ningún problema en que se borraran los que ya has leído siempre y cuando los volvieran a poner cuando volvieras a acercarte a ellos). Es el mismo problema filosófico de si el mundo desaparece cada vez que cierras los ojos y vuelve a aparecer cuando los vuelves a abrir. (Si no recuerdo mal, eso es lo que afirmaba George Berkeley.) No se trata de demostrar que eso no sucede, sino de responder: ¿y si así fuera, qué más daría?

No sé si logro explicarme. Sospecho que sin esa intuición espacial, sería inconcebible pensar en los números naturales, o mejor dicho, que todo recorrido secuencial tiene soporte geométrico en algo como dicha cinta.

Para mí es clave que sea posible "imprimir" una cierta información y dejarla "memorizada" en cierto casillero de esa cinta. De lo contrario, el intento de volver atrás, por ejemplo, buscando encontrar elementos anteriores de una sucesión, se volvería una acción confusa o borrosa.

Yo diría que todo eso es más teoría del conocimiento que matemática, en el sentido de que, cualquier postura que adoptes al respecto no influye en lo que puedas decir o dejar de decir sobre los números naturales.

El inconveniente que ví en esto es que cuando invitás al lector a hacer un programa en la computadora para comprobar que todo funciona de forma concreta,
lo que digo es que eso no es así.
Algo tan sencillo como sumar un 1 a un número natural es algo que puede tener problemas de implementación complejos, aún cuando se lleve a cabo el programa bajo la hipótesis de que durante la ejecución no habrá limitaciones de memoria.

Sobre esto te ha respondido geómetracat, que sabe del tema mucho más que yo (como se ve sin más que leer su mensaje), pero, en cualquier caso, yo incluía esos problemas de implementación a los que te refieres en las limitaciones de memoria, es decir, limitaciones de memoria son tanto la falta de disco duro o de RAM como el hecho de que un lenguaje de programación admita enteros hasta un máximo valor, o algo así.

Pero todo lo que digo de "programar a un ordenador" lo puedes entender como "diseñar un programa de ordenador en un lenguaje dado", olvidando las limitaciones de memoria, incluyendo las que digan que una variable entera sólo puede almacenar hasta un valor máximo, etc. Si luego un ordenador no es capaz de ejecutar un programa "como debería" por limitaciones de memoria, el problema lo tiene el ordenador, no el programa. Si éste está bien diseñado, expresa un algoritmo válido para calcular lo que se pretende, con independencia de si un ordenador lo ejecuta correctamente o no. Si no lo ejecuta correctamente, siempre se podría construir un ordenador con más capacidad que lo hiciera. No doy más detalles porque geómetracat lo ha explicado mejor de lo que podría hacerlo yo.

Si en vez de usar dígitos, como hice yo, uno simplemente usa "concatenación de caracteres con forma de palitos": |||||||||,
y sumar 1 lo implemente como agregar un palito a la cadena,
hacer operaciones aritméticas con eso será más ineficiente a la larga,
aunque implementar la operación "siguiente de" es tan sencillo como agregar un palito.

Nada es ineficiente si dispones de todo el tiempo del mundo.  Y a efectos teóricos, disponemos incluso de más tiempo.  ;D

Pero bueno, creo que es interesante tratar de aprender algo nuevo, no sólo pelearse con la vida.

Así que aquí va mi intento de programa con la máquina de Turing.

Me molestan las máquinas de Turing que no tienen un casillero inicial.
Así que de izquierda a derecha dispondré las casillas, a partir de un casillero inicial.

Eso es irrelevante, porque se puede demostrar que toda función computable con una máquina dotada de una cinta doblemente infinita se puede computar también con una máquina con una cinta con una casilla inicial. Pero tendrías que plantearte esas "molestias" más o menos arbitrarias que tienes con cierta frecuencia. Es como si dices que aceptas trabajar intuitivamente con números naturales, pero no con enteros o racionales, cuando en realidad es lo mismo. Si puedes razonar informalmente con números naturales y con dos signos + y  -, puedes razonar con números enteros.

Asumo el alfabeto: { 1 } (el caracter "uno").
También denotaré con 0 a la casilal en blanco (para hacerla un poco más visible).
Considero el estado Q1 como activo y Q0 como el estado terminal y pasivo.

Al iniciar, el cabezal de impresión está parado sobre un casillero de la cinta.
Tiene permitido imprimir un caracter del alfabeto, o borrar lo que esté impreso.
Luego, tiene permitido mover el cabezal a Izquierda (I), Derecha (D), o Centro (C, quedarse quieto).
El estado puede cambiar a otro estado activo o a un estado pasivo.

El algoritmo A sería éste:

__ Si la máquina está en el estado activo Q1 (el único posible en este caso), entonces
________ Si el casillero actual está en blanco (0):
________________ Mover hacia C (quietud), imprimir 1, y cambiar el estado a Q0.
________ Si el casillero actual tiene un (1):
________________ Mover hacia D, imprimir 1, cambiar el estado a Q0.


Espero haberlo hecho bien.

Y si no, pues estoy abierto a recibir los castigos correspondientes.

En tal caso sería mi primer programa de Turing.

Pues está perfecto.  :aplauso:

La única observación es que el caso de que la lectura sea 0, aunque puedas haberlo considerado por no dejar el programa a medias, es irrelevante para el cálculo de la función sucesor, en el sentido de que da igual lo que digas que hace la máquina en ese caso, que funcionaría exactamente igual. Aquí supongo el convenio por el que, cuando quieres que una máquina de Turing calcule el valor de una función sobre unos números \( a_1, \ldots, a_n \), la forma de "decírselo" es ponerla sobre la última casilla del último número. Por ejemplo, si los argumentos son 2, 2, 3, el punto de partida sería:

1 1 1 0 1 1 1 0 1 1 1 \( \underline 1 \)

y el resto de la cinta en blanco.

Y si ese es el programa de la función "siguiente", pues tengo algunas moscas que me dan vueltas en la mente...

Pues ése es, sí.

10 Junio, 2023, 12:50 pm
Respuesta #31

Carlos Ivorra

  • Administrador
  • Mensajes: 11,883
  • País: es
  • Karma: +0/-0
  • Sexo: Masculino
    • Página web personal
Hola a todos. Paso por aquí principalmente a saludar y a decir que, aunque últimamente estoy participando poco en el foro (mucho trabajo), seguí con interés el hilo de la inducción hasta \( \epsilon_0 \), y estoy siguiendo este nuevo hilo de la aritmética primitiva recursiva.

Pues bienvenido al hilo  :)  Me alegra que te interese.

Me ha llamado bastante la atención esto:
De hecho, existe una teoría más débil que ARP, conocida como la Aritmética de las Funciones Elementales  que es como ARP, pero con funtores únicamente para la suma, el producto y la exponenciación, y la "Gran Conjetura de Friedman" afirma, más o menos, que cualquier teorema con enunciado puramente aritmético, y no diseñado con mala idea para que no sea así, es demostrable en AFE. En particular, la conjetura afirma que el Último Teorema de Fermat tiene que ser demostrable en AFE, luego, en particular, en ARP, aunque nadie ha probado que sea así.
No estoy familiarizado con AFE pero parece una teoría extremadamente débil. Entiendo que la idea de Friedman debe ser que, de todos los usos de argumentos generales sofisticados en la demostración del UTF (p.ej. la maquinaria de geometría algebraica) y que claramente no son formalizables en AFE, se pueden extraer y formalizar los argumentos concretos que se necesitan en la demostración y probarlos en AFE. Si es así me parece una idea interesante, pero soy un tanto escéptico al respecto. Sí lo veo bastante más plausible en PA.

Yo tampoco estoy familiarizado con AFE. De hecho, no sabría decir qué se puede hacer exactamente en ARP que no pueda hacerse en AFE, porque una vez cuentas con la función exponencial (construirla en AP cuesta un poco) ya se pueden condificar muchas cosas, pero ciertamente, hay cosas que se pueden hacer en ARP que no se pueden hacer en AFE, porque en ARP se puede probar la consistencia de AFE. Te adjunto un pdf que discute la conjetura de Friedman. Precisamente dice que es una conjetura contra la que muchos matemáticos tendrán serias reservas, pero que, a la vez, resulta plausible para los especialistas.

Entiendo que la esencia de la conjetura de Friedman es que cualquier resultado "razonable" sobre números naturales que admita una prueba sofisticada tiene que admitir también una prueba "elemental", como sucede con el teorema de los números primos o el teorema de Dirichlet sobre primos en progresiones aritméticas. Otra cosa, claro, es lo enrevesada que podría ser la prueba elemental y si puede ser tan elemental que quepa en AFE.

De todas maneras, para calcular la función sucesor en la realidad, una máquina de Turing sigue siendo matar moscas a cañonazos.

Sí, pero, conociendo a argentinator, después de sus reservas sobre la función sucesor, es probable que vengan más sobre otras funciones, así que, si le valen las máquinas de Turing, simplificamos futuros análisis.

10 Junio, 2023, 05:15 pm
Respuesta #32

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,796
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
La última frase no la entiendo: dices que una máquina de Turing es más complicada que ¿qué cosa? Porque diría que estás diciendo que es más complicada que ella misma, así que no he entendido a qué hacías referencia.

Más complicada que los mismos números naturales y sus funciones primitivas definidas "en el aire".
Pues además la máquina de Turing es tan imaginaria como los naturales, y encima con más aparatología en derredor.


10 Junio, 2023, 06:06 pm
Respuesta #33

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,796
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino

Ahora un poco de "off-topic" sobre las cuestiones de implementación real de la función sucesor.
Y bueno, con la computadora imaginaria siempre es todo más fácil.  :P

Sí, tras postear mi mensaje me dí cuenta que podía haber nombrado la máquina de Turing,
pero no agregué ninguna aclaración, y además no es una máquina real.
Es un mecanismo imaginario, más complicado que lo que se está queriendo representar con eso.
No es tan imaginaria, hay gente que se ha dedicado a construir alguna real (a efectos demostrativos). Mira por ejemplo: https://spectrum.ieee.org/032610-diy-turing-machine

Hola geometracat.

Sí, efectivamente tengo visto que hay gente que ha construido máquinas de Turing de verdad... pero siempre con memoria limitada.
El mismo creador de la máquina dice esto:

Citar
The tape in my machine is a 1000’ roll of white 35mm film leader.

A lo mejor habría que agregarle algún mecanismo para que se le pueda agregar más cinta bajo demanda.

En ese caso sí sería una Máquina de Turing real.  :o

Es más fácil (en el sentido de escalable) empalmar un trozo de cinta
que ampliar la RAM o los discos rígidos o los procesadores, o lo que sea que se invente en el futuro para tener más y más almacenamiento, que se vuelve más y más complejo y retorcido.

De hecho, a lo mejor esto que decís de las máquinas de Von Neumann,
pues en cierto modo han desvirtuado mucho las cosas,
en el sentido de que se hace parte del diseño la necesidad de tener cada casillero de memoria indexado de antemano.

La Máquina de Turing no indexa las posiciones de memoria.

En la computación antigua, los archivos se almacenaban en cintas,
y yo mismo he programado así, así que no sé de qué me sorprendo.

Pero bueno, esto me hace pensar que, entonces, la manera más adecuada
de simular lo que hace la Máquina de Turing sería usar un archivo de texto
en vez de un tipo de datos entero, como argumento de la función "siguiente".

Esto se haría así, porque un archivo es el resabio de lo que antiguamente se hacía con las cintas: es una estructura de datos de tamaño flexible, de acceso secuencial
(aunque a veces puede accederse en forma no secuencial, no está esto asegurado),
y que puede leerse y reescribirse byte a byte.

Y los estados, en lenguajes como C, Fortran, Pascal, BASH,
bien pueden ser etiquetas a donde el programa salta con un "goto",
tras leer un caracter del archivo, y procesarlo con un switch-case o similar.

Pero bueno, como sea, aunque yo reformule mi programa en C mediante estas nuevas convenciones, la verdad es que los problemas de acceso o referencia a memoria son los mismos.

Citar

Pero hay otras formas de hacer esto. Por ejemplo, podrías ir guardando el número en un disco duro en lugar de en memoria RAM, con lo que tienes muchísima más capacidad de almacenamiento. O podrías usar varios ordenadores en red, de manera que "añadir" más memoria significaría "añadir más ordenadores" que fueran capaces de acceder a más memoria (que es el camino que se emplea para tratar con datos masivos).

En resumen, que las complicaciones son más de carácter técnico que filosófico. No hay ningún problema real en guardar números grandes y calcular el siguiente, más allá de que la arquitectura de los ordenadores es como es, por motivos de versatilidad y de eficiencia. Pero aún con los ordenadores actuales hay muchas soluciones que realmente solo requieren añadir "más memoria".

Cuando estás diciendo que "sólo requieren más memoria", estás asumiendo que ese problema es soslayable, porque no atañe a la cuestión filosófica.

Es que el número de complicaciones crece con el tamaño de los datos.
Puedo almacenar dígitos en un archivo gigante en un disco duro,
pero los datos en un disco duro también se indexan con números enteros.
El tamaño de un archivo se guarda por ahí como un número entero.

Entonces, yo no digo que no sea posible, de hecho en mi post lo dejé en duda,
pero a mí me parece que cuanto más grande sea el número de dígitos,
mayores serán los problemas para almacenarlo,
porque luego hay que hacer referencia a ese "dato".
Si un dato requiere almacenarse en muchos archivos, porque no cabe en uno,
tendré que indicarlo de alguna manera,
haciendo referencia a esos archivos,
y esos archivos tendrán o un nombre o una ubicación,
que si requiero un número aún mucho más grande,
pues los mismos nombres de archivo comenzarán a ser escasos,
y tendré que hacer una referencia indirecta,
almacenando nombres grandes de archivo en otros archivos,
y así sucesivamente.

Yo creo que la solución podría ser pensar en un diseño escalable,
pero que se haga de una manera recursiva,
de modo que se clasifique a los números naturales según cierto grado de complejidad.
La idea sería, tras considerar un número natural de tamaño \(S_n\)
(donde \(S_n\) es una sucesión creciente que cuenta el número de dígitos de un natural),
almacenar una referencia de digamos "orden 0" (espero que se entienda lo que prentedo hacer),
que apunta a uno o más archivos de "orden 1",
cuyos datos apuntan a uno o más archivos de "orden 2",
y así hasta llegar al orden \(n\), que es donde se almacenarían
efectivamente los dígitos del número.

Tan complicado me resulta imaginar números grandes, como complicado es hacer referencia a los lugares en que se almacena la información de ellos al representarlos en un medio de almacenamiento.

Y considero que esa analogía en la complicación es parte ineherente de los números naturales.
Por eso me cuesta tomarme a la ligera que sea lo mismo pensar en un 25 que en un 10324781234781247812349781032497109.

Es más costoso calcular el siguiente de un número grande.
El exceso de costo puede volverlo imposible en la vida real.
¿Y en la mente?

__________________

En cuanto a electrónica digital, algo conozco, pero no tengo cómo hacer eso en casa,
y si tuviera, no es fácil que otros usuarios del foro lo reproduzcan.

Todo bien con las observaciones que me hiciste.
Pero Carlos alentó al público a que programe las funciones en cuestión en su computadora,
y no quería dejar pasar el hecho de que no es todo tan simple como podría uno imaginar.

_________________

En cuanto a dificultad... mmmm. Sí, computar la función siguiente parece lo más fácil de todo. Pero me vuelan unas moscas molestas, que espero que me aclaren, y que indicaré en el siguiente mensaje, para no mezclar tantos asuntos.

10 Junio, 2023, 06:11 pm
Respuesta #34

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,796
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
A lo mejor habría que agregarle algún mecanismo para que se le pueda agregar más cinta bajo demanda.

En ese caso sí sería una Máquina de Turing real.  :o

Es más fácil (en el sentido de escalable) empalmar un trozo de cinta
que ampliar la RAM o los discos rígidos o los procesadores, o lo que sea que se invente en el futuro para tener más y más almacenamiento, que se vuelve más y más complejo y retorcido.


Bueno, acá me voy a poner a discutir conmigo mismo, porque no me cierra esto.

Creo que me equivoqué al decir que agregar un trozo de cinta era algo fácil.
De hecho, agregar más cinta (o más memoria) bajo demanda,
debiera ser un mecanismo automatizado que forme parte de la máquina.

Así que la máquina tendría que procurarse el material, mover un brazo robótico que agregue el trozo de cinta, y así sucesivamente, sin asistencia ni humana ni de ningún tipo.
Pero entonces sería un mecanismo automatizado para buscar recursos a fin de cumplir sus objetivos.

Ahora bien, ¿no será que seres de otras dimensiones han creado nuestro Universo como parte de su estrategia de aumentar la RAM de su cachibache de Turing, que está calculando el siguiente de un número gigantesco?
Pues hay que hacer lo que sea necesario para cumplir con ese cálculo.

10 Junio, 2023, 06:17 pm
Respuesta #35

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,796
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
Decía que me vuelan algunas moscas al usar la Máquina de Turing para calcular el siguiente.

La función "siguiente" le calcula el siguiente a cualquier cosa.
Si en una cinta tengo:

0 0 1 1 0 0 0 1 0 1 1

el siguiente será:

0 0 1 1 0 0 0 1 0 1 1 1,

Tengo que asumir de entrada que la cinta tiene representado un número natural,
o sea, sólo un número finito de 1's, y nada más que eso,
que el cabezal está justo en la posición del último 1.

Y por otra parte, ¿cómo sé desde dónde arranca el primer 1 que representa al número natural dado?

Por eso creo que prefiero que la cinta tenga un casillero inicial.
Pues a partir de ahí comienzo a agregar 1's a la derecha.
Y si tengo que determinar si lo que tengo almacenado es o no una lista finita de 1's,
tengo un punto de partida concreto desde donde comenzar a analizarlo.


10 Junio, 2023, 07:20 pm
Respuesta #36

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,796
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
Bueno, ahí voy con todas las funciones primitivas, en C, pero reformuladas con archivos,
que simularán la cinta de Turing.

En el archivo se almacenarán los caracteres ' ' (espacio en blanco) y '|' (palito vertical).


#include <stdio.h>
#include <stdbool.h>

bool Mover_Izquierda(FILE *cinta) {
  return (0 != fseek(cinta, SEEK_CUR, -1));
  // Si la cinta está "rebobinada", hay un error.
}

bool Mover_Derecha(FILE *cinta) {
  if (!feof(cinta)) {
     fseek(cinta, SEEK_CUR, +1);
     return true;
  }

  // La cinta llegó al final: hay que agregar un casillero en blanco.
  return (fwrite(" ", 1, 1, cinta) == 1); // Retorna false en caso de error.
}

bool Mover_Centro(FILE *cinta) {
  return true; // No se hace nada...
}

char Leer_Casillero_Actual(FILE *cinta) {
  char buffer[2] = "";
  fread(buffer,1,1,cinta);
  Mover_Izquierda(cinta);
  // Este último movimiento es para dejar el cabezal en donde estaba,
  // pues la operación de lectura mueve el puntero interno del archivo.

  return buffer[0]; 
}

void Escribir_Casillero_Actual(FILE *cinta, char simbolo) {
  char buffer[2] = { simbolo, };
  fwrite(buffer,1,1,cinta);
  Mover_Izquierda(cinta);
  // Este último movimiento es para dejar el cabezal en donde estaba,
  // pues la operación de lectura mueve el puntero interno del archivo.
}

void S(FILE* cinta) {
  Q1: // Estado activo, por defecto aquí.

  if (cinta == NULL) {
    goto Q_ERROR;
  }

  if (false == Mover_Derecha(cinta)) {
     goto Q_ERROR;
  }

  Escribir_Casillero_Actual(cinta,'|');
 
  Q_ERROR:
     puts("ERROR");

  Q0: // Estado final.

  ;
}

void c0(cinta) {
  FILE * freopen (NULL, "w+", cinta);
  // Esta operación elimina todos los datos de la cinta, y la pone en blanco.
}

void proyeccion(cinta, int i, int n) {
   // MMMMMMMM... Acá tengo tengo dudas de las especificaciones ...
   // Lo dejo sin hacer por un rato.
}

int main(void) {
  // Asumo que el archivo "cinta.txt" ya exite en el sistema.
  FILE *cinta = fopen("cinta.txt", "r+");

  c0(cinta);
 
  S(cinta);
 
  proyeccion(cinta, 3, 4);

  return 0;
}


10 Junio, 2023, 07:26 pm
Respuesta #37

Carlos Ivorra

  • Administrador
  • Mensajes: 11,883
  • País: es
  • Karma: +0/-0
  • Sexo: Masculino
    • Página web personal
Pero Carlos alentó al público a que programe las funciones en cuestión en su computadora,
y no quería dejar pasar el hecho de que no es todo tan simple como podría uno imaginar.

Pero para lo que realmente importa sí que es así de simple. Cuando hablo de "programar un ordenador", lo que importa es el programa, no lo que haga el ordenador. Si tú puedes crear un programa de ordenador, en cualquier lenguaje, y razonar que, por ejemplo, cuando le das un número natural determina si codifica o no un ordinal, eso pone en evidencia que el concepto de ordinal está bien definido, que no hay duda de que, dado un número natural, se puede decir objetivamente si representa o no un ordinal, porque todo se reduce a aplicar un algoritmo. Obviamente, si el número de entrada en muy grande, el ordenador puede fallar, pero eso no significa que el algoritmo diseñado esté mal. Es la existencia del algoritmo y no si el ordenador puede o no manejar los datos, lo que determina que el concepto de "ordinal" (como número natural) está bien definido.

Un ejemplo de por qué estas observaciones tuyas no vienen al caso:

Así que la máquina tendría que procurarse el material, mover un brazo robótico que agregue el trozo de cinta, y así sucesivamente, sin asistencia ni humana ni de ningún tipo.
Pero entonces sería un mecanismo automatizado para buscar recursos a fin de cumplir sus objetivos.

Según leo en internet, se estima que el número de átomos del universo es menor que \( 10^{100} \). Resulta entonces que es fácil programar una máquina de Turing para que calcule la función \( x^y \), pero si a esa máquina le das como entrada \( 10, 100 \) (y no necesitas mucha cinta para meter esos datos), para acabar su cálculo necesitará que su cinta tenga más casillas que átomos hay en el universo. ¿De qué te valen entonces tus brazos robóticos o lo que sea?

Ninguna máquina de Turing podrá calcular nunca \( 10^{100} \) en la práctica, al menos no si tiene que ofrecer el resultado con la forma usual en la que las máquinas de Turing codifican los números naturales (otra cosa sería que la programaras para que diera como respuesta las cifras decimales del resultado, por ejemplo). Pero si tienes un programa del que puedes demostrar que hace que la máquina calcule \( x^y \) para valores cualesquiera de \( x, y \), si luego a la máquina le falta cinta, ¡eso da igual! Si has razonado que el programa está bien, pues está bien.

Y del mismo modo que podemos despreciar si una máquina de Turing puede quedarse irremediablemente sin cinta, también podemos despreciar todos los problemas prácticos que puede tener un ordenador para ejecutar un programa. Lo que importa es si el programa se puede escribir en un lenguaje de programación cualquiera y si no tiene "bichos" en el sentido de que siempre hará lo que se espera que haga (si el Universo lo permite).

Decía que me vuelan algunas moscas al usar la Máquina de Turing para calcular el siguiente.

La función "siguiente" le calcula el siguiente a cualquier cosa.
Si en una cinta tengo:

0 0 1 1 0 0 0 1 0 1 1

el siguiente será:

0 0 1 1 0 0 0 1 0 1 1 1,

Tengo que asumir de entrada que la cinta tiene representado un número natural,
o sea, sólo un número finito de 1's, y nada más que eso,
que el cabezal está justo en la posición del último 1.

En general, cada máquina de Turing sabe para qué sirve. Quiero decir que si una máquina de Turing está pensada para calcular \( x^y \), entonces el programa da por hecho que tendrá dos números naturales escritos en la cinta y, si sólo tiene uno, probablemente la máquina se volverá loca y no acabará nunca, salvo que le pongas algo más de código de detección de errores y compruebe que, si cuando se acaba el primer número yendo hacia la izquierda hay dos blancos seguidos, es que los datos están mal.

Y por otra parte, ¿cómo sé desde dónde arranca el primer 1 que representa al número natural dado?

La máquina puede encontrar el principio moviéndose hacia la izquierda hasta encontrar el primer 0.

Por eso creo que prefiero que la cinta tenga un casillero inicial.
Pues a partir de ahí comienzo a agregar 1's a la derecha.
Y si tengo que determinar si lo que tengo almacenado es o no una lista finita de 1's,
tengo un punto de partida concreto desde donde comenzar a analizarlo.

A la máquina le da igual. Lo usual es exigir a una máquina que tiene que calcular una función que nunca lea ninguna casilla situada a la izquierda de la casilla anterior en la que empieza el primer dato. Quiero decir que si la entrada es

\( 0011101111011110\underline 1 \)

y la máquina "sabe" que tiene que leer cuatro números, si el programa es "bueno" nunca leerá la primera casilla que he escrito con un 0 ni las que están a su izquierda. En cuanto llegue al segundo 0 parará y no irá nunca más a la izquierda.

10 Junio, 2023, 08:09 pm
Respuesta #38

Carlos Ivorra

  • Administrador
  • Mensajes: 11,883
  • País: es
  • Karma: +0/-0
  • Sexo: Masculino
    • Página web personal
Ojo, me acabo de dar cuenta de que aquí he metido la pata:

No copio todo lo que pones en el mensaje siguiente sobre cómo programar la función sucesor, pero, digo yo, en lugar de pelearte con los intestinos de Python o C, ¿no te vale con que una máquina de Turing puede calcular trivialmente la función S?

Es muy fácil programarla para que si le das como argumento un número, por ejemplo \( a = 5 \), así:

\( 111111\underline1 \),

donde el subrayado indica la casilla de la cinta que leerá la máquina cuando empiece, la máquina se detenga así:

\( 1111111\underline1 \).

El programa consiste únicamente en que se mueva una casilla a la derecha e imprima un 1. Fin.

Ese programa está calculando la función sucesor.

Con los convenios usuales, una máquina de Turing computa una función \( f \) si, cuando le damos unos datos en la cinta, digamos \( a_1,\ldots, a_n \), termina con \( a_1,\ldots, a_n, f(a_1,\ldots, a_n) \) y, entendiéndolo así, la máquina que he descrito no computa la función sucesor. Por ejemplo, si le damos como entrada:

\( 111111\underline1 \)

la salida debe ser:

\( 111111101111111\underline1 \)

Así se calcula \( S(6) = 7 \).

10 Junio, 2023, 08:27 pm
Respuesta #39

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,796
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
Ojo, me acabo de dar cuenta de que aquí he metido la pata:

No copio todo lo que pones en el mensaje siguiente sobre cómo programar la función sucesor, pero, digo yo, en lugar de pelearte con los intestinos de Python o C, ¿no te vale con que una máquina de Turing puede calcular trivialmente la función S?

Es muy fácil programarla para que si le das como argumento un número, por ejemplo \( a = 5 \), así:

\( 111111\underline1 \),

donde el subrayado indica la casilla de la cinta que leerá la máquina cuando empiece, la máquina se detenga así:

\( 1111111\underline1 \).

El programa consiste únicamente en que se mueva una casilla a la derecha e imprima un 1. Fin.

Ese programa está calculando la función sucesor.

Con los convenios usuales, una máquina de Turing computa una función \( f \) si, cuando le damos unos datos en la cinta, digamos \( a_1,\ldots, a_n \), termina con \( a_1,\ldots, a_n, f(a_1,\ldots, a_n) \) y, entendiéndolo así, la máquina que he descrito no computa la función sucesor. Por ejemplo, si le damos como entrada:

\( 111111\underline1 \)

la salida debe ser:

\( 111111101111111\underline1 \)

Así se calcula \( S(6) = 7 \).

Oh no. Tengo que hacer todo de nuevo.

Encima ahora también, por culpa de geometracat, voy a tener que programar con compuertas digitales.