Autor Tema: *Lab*: El Halting Problem con un enfoque experimental

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

13 Enero, 2012, 08:03 pm
Respuesta #20

Elius

  • $$\Large \color{#5e8d56}\pi\,\pi\,\pi$$
  • Mensajes: 399
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
Hola,

De todas maneras, creo que tu planteamiento es el siguiente (corrígeme si me equivoco). Consideras los programa (con 1 input digamos, para no complicarnos) P(n). Tienes otro programa U(m,n) que ejecuta el programa m con input n. Digamos que el código de U es N. ¿Qué pasa si intentamos ejecutar U(N,N)? U simula la ejecución de U con input N. Pero aquí falla algo: U necesita dos inputs y ahora sólo tiene uno, así que el programa falla por falta de inputs para U.
Bien, esto es cierto, pero no es lo que hace Turing. (...)
Tengo claro que no es lo que hace Turing. Por eso dividí los casos.

1) Programa que ejecuta con su propio código como input (Turing no ejecuta, supone algún algoritmo de decisión para anticipar si el programa objeto para o no).

Luego en el caso 2 pido un programa similar al de Turing, pero no quiero adelantarme, es otro caso.

Citar
(...) Te voy a mostrar que lo que hace Turing funciona de verdad, y lo voy a mostrar con un programa que se puede programar en la vida real (yo no lo voy a hacer, pero se puede hacer, y no me extrañaría que alguien lo hubiera hecho). del tipo que pides: un programa que se ejecuta a sí mismo pero sin embargo nunca acaba.

Considera U(m,n) un programa universal para programas con un input: si m es el código de un programa con un input P y n es el input, U(m,n) simula la ejecución de P(n).
Ahora considera el siguiente programa con un sólo input, U'(m). U'(m) primero hace una copia del input m y después ejecuta U(m,m). Bien, ahora sea N el código de U'. ¿Qué pasa si hacemos U'(N)? Veamos: U'(N) hace una copia de N y ejecuta U(N,N): es decir, simula la ejecución de U' con input N. Hemos vuelto al principio: esto es un bucle infinito. Si analizas bien este programa (que como he dicho, puede programarse de verdad) solventa la posible falta de input haciendo contínuamente copais de sí mismo e introduciéndolas como input para sí mismo en el siguiente paso: esa es la salida a la situación del párrafo anterior.

Si te fijas, lo que he hecho es exactamente lo mismo que hace Turing para llegar a la contradicción, sólo que en vez de aplicarlo a un programa que resuelve el problema de la parada (que no existe), lo he aplicado a un programa que sí existe: un programa universal.

Saludos

Te agradezco mucho, Óscar, que me hayas hecho notar que faltan restricciones.

Ya agregué como condición que los programas que tengo en cuenta son aquellos que no tienen un looping explícitamente preestablecido, ni los que forman cadenas infinitas de llamados a funcione o procesos.

Y me faltó una que me parece la más idónea para evitar "trampas": considero solamente los programas que tienen un número fijo y obligatorio de argumentos. Eso no quita generalidad, porque si uno quiere considerar casos con menos argumentos hace otro programa y ya.

Por el momento, no quiero tener en cuenta los casos en que un programa está hecho para fallar, aunque más adelante deberé considerarlos porque es lo que usa Turing.

Saludos!






13 Enero, 2012, 08:11 pm
Respuesta #21

Elius

  • $$\Large \color{#5e8d56}\pi\,\pi\,\pi$$
  • Mensajes: 399
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino

Se considerará que funciona si el programa objeto se completa con un estado final, o queda ejecutando un ciclo infinito, pero se considerará que no funciona si produce error por falta de argumentos o se queda indefinidamente esperando el input.



Lo de esperar un input es un poco ambiguo; qué hace el ordenador mientras espera o cómo espera, no lo veo claro. Por ejemplo, ésta es una espera programada en actionscript (el lenguaje de Flash Macromedia, el de los típicos juegos).

stop();
seg = 2;
espera = function () {
    play();
    clearInterval(I);
};
I = setInterval(espera, seg*1000);

Hace que el ordenador espere dos segundos, y después "play", que quiere decir que sigue corriendo a la línea que haya después de esta rutina, la que sea (no la hay porque no la escrito).

 Bien, aunque no se vea, ahí hay un bucle, pero está camuflado por unos comandos, metidos en una función, en los que no parece haber ningún direccionamiento.  En todas las paradas, salvo en las que pertenecen al final de una rutina -o al menos de una subrrutina completa- hay un bucle camuflado. Luego es un bucle o es la ejecución completa de un bloque o parte del programa. No sería por "falta de argumento" del programa ejecutor, sería que el programa ejecutor ha llegado a un lugar donde puede pararse "legalmente", porque no existen lugares no legales para que se pare; bueno, quizá puedan existir si se desenchufa el ordenador.

Saludos.



 

feriva,
no entiendo este código:

stop();
seg = 2;
espera = function () {
    play();
    clearInterval(I);
};


Si stop() hace lo que dice la palabra, de sólo comenzar ya para. Y luego, necesitaría el código de play() y clearInterval(I) para entender más.

Saludos!


13 Enero, 2012, 09:11 pm
Respuesta #22

feriva

  • $$\Large \color{#a53f54}\pi\,\pi\,\pi\,\pi\,\pi\,\pi\,\pi$$
  • Mensajes: 11,339
  • País: es
  • Karma: +1/-0
  • Sexo: Masculino
Citar

feriva,
no entiendo este código:

stop();
seg = 2;
espera = function () {
    play();
    clearInterval(I);
};


Si stop() hace lo que dice la palabra, de sólo comenzar ya para. Y luego, necesitaría el código de play() y clearInterval(I) para entender más.

Saludos!



¿Ves? Y, sin embargo, verás que -si te descargas un Flash Macromedia de prueba- http://macromedia-flash.uptodown.com/descargar - corre perfectamente; puedes cambiar la variable de los segundos (seg) y comprobarlo varias veces; detrás tendrías que poner una línea o alguna rutina para que pasara algo.

 Con esto puedes ver que "stop" es sólo una palabra que quiere decir lo que el programador del sistema de programación quiere que diga; y su funcionamiento es variable. Esto pasa con el C, con el java, con el javascript o con el lenguaje que quieras; son programas de usuario, un poco más complicados que el Word y esos otros, pero programas de usuario; y, por tanto, las conclusiones que puedas sacar a tenor de su funcionamiento pueden ser erróneas, del mismo modo que no puedes deducir cómo se divide a mano si te basas en los resultados de una calculadora; das unos botones, pero no eres tú el que divides.

Saludos.

14 Enero, 2012, 12:22 am
Respuesta #23

Óscar Matzerath

  • $$\Large \color{#c88359}\pi\,\pi\,\pi\,\pi$$
  • Mensajes: 567
  • Karma: +0/-0
  • Sexo: Masculino
Hola,


Pero si nos permitimos redefiniciones de las condiciones iniciales del programa que representa a la MT de Turing, yo podría agregar lo siguiente, para evitar que Turing use el código de la máquina testeadora como input:

@if '%0'=='%1' ( echo Turing: esto no es válido   Compara el input con su propio nombre
goto :fin )

@if '%2'=='' universal.bat %1 %1
%1 %2
:fin

Output:

C:\> UNIVERSAL UNIVERSAL UNIVERSAL
Turing: esto no es v?lido

C:\>

Tienes razón, pero por un lado eso no invalida para nada la demostración de Turing (porque ahora todo programa con dos inputs iguales para), y por otro lado ese problema se puede solventar de varias maneras (por ejemplo considerando el mismo programa que te propuse, pero haciendo que ignore el input que le metas y se dedique a copiarse y ejecutarse a sí mismo).




Citar
Lo que me parece incomprensible es que para no sacar el simple y humilde mensajito "Falta un argumento", se hace entrar al proceso no ya en un bucle infinito, que sólo consume tiempo, sino a una cadena potencialmente infinita de llamadas que pueden hacer colapsar la memoria de la máquina. Los sistemas operativos tienen defensas para casi todo, pero no para la proliferación de procesos.

En resumen, no llega a terminar normalmente, en el caso "ingenuo" (sin sentencias "ad hoc"), porque se queda sin input; y en el caso "malicioso" (porque sabe que se queda sin input pero trata de ocultarlo), porque se queda leyendo infinitamente su input, o su input es infinito, como prefieras.

En ningún caso le serviría a Turing, me parece.

Hombre, no creo que "incomprensible" sea la palabra adecuada. Este programa es estúpido, pero creo que es, salvo pequeñas variantes, la única posibilidad de que un programa haga lo que pidas (que se ejecute a sí mismo, en un sentido bastante fuerte), y obviamente está pensado únicamente como ejemplo de lo que pedías. El input del programa es finito: es el propio programa. El programa hace exactamente lo que debe hacer, tomar un único input (él mismo) y ejecutar su programación. Que en el proceso haga infinitas llamadas a sí mismo es irrelevante. Es un hecho que el programa funciona (el ordenador lo ejecuta vaya) y nunca para, que era lo que pedías inicialmente. Obviamente, si empiezas a poner condiciones cada vez más restrictivas no habrá ningún programa que las satisfaga.

De todas maneras, echa un vistazo a la siguiente variación:
Considera una máquina universal U(m,n). Ahora sea U'(n) la máquina que hace lo siguiente: modifica n añadiendo al final del código del programa una sentencia estúpida, por ejemplo que imprima algo en pantalla. Digamos que este nuevo código es n'. A continuación el programa computa U(n,n'). Sea N una modificación estúpida del código de U' y considera U'(N). Primero se modifica el programa N de forma estúpida con código N' y se ejecuta U(N, N'). Pero U(N,N') computa exactamente lo mismo que U'(N') (más una salida en pantalla). Y esto te hace un código N'' que hace lo mismo que N y que N' (salvo impresiones en pantalla), y te computa U(N',N''), etcétera. El resultado es el mismo que antes, y ahora no hay autoaplicación por ningún sitio (los programas son todos distintos, aunque tengan una parte en común). Así que si ves un problema en esto, el problema no viene de la autoaplicación de programas (por lo menos en sentido estricto).

Sobre la última afirmación, no veo por qué no le serviría a Turing (más bien no entiendo en qué sentido lo dices).



Citar
El caso Ivorra también es "ad hoc": en vez de poner dentro del código una previsión ante la falta de input, pone como hipótesis que ante la cinta en blanco entra en loop o termina "bien". En ese caso siempre hay una respuesta ya predeterminada, y no se puede llegar a la contradicción que necesita Turing. Supongamos que ante la falta de input la máquina interna loopea. La máquina externa para, y siempre es así, no podemos agregar: "y si la máquina interna para, la máquina externa loopea", porque ese caso no se da nunca. Ergo, no hay contradicción.

Es que para empezar a Turing le dan igual los inputs, en sus máquinas los inputs son únicamente una convención "psicológica", nada más. Una máquina con la cinta en blanco hará lo que le mande su programación. Sobre lo que dices de que la demostración de Turing no vale, no sé si lo entiendo bien (¿quién es la máquina interna y la externa? ¿la externa es la que decide si una máquina dada para o no y la interna sobre la que se ha de decidir si para?) De todos modos, en la demostración de Turing lo único que hace falta es suponer que la máquina que decide si otra con un input dado para o no, siempre para (y funciona bien), lo que haga si no le das un input a la máquina interna es irrelevante, porque siempre tiene input en la demostración.



Citar
En el caso que planteé yo, de autoaplicación pura sin predicción, en el caso de las MT es una MUT que llama a otra MUT que no tiene máquina objeto que ejecutar.

Considera que no es simplemente que faltan datos en la cinta, en el caso de la MUT si la cinta está en blanco FALTA UNA MÁQUINA COMPLETA.

Sí, se puede decir, "bueno, si no tengo input para pasarle considero que es una máquina con la cinta en blanco", pero en ese caso no le queda otra alternativa que loopear, no puede parar porque NO TIENE MANERA DE "SABER" que TODA la cinta está en blanco. Tiene que seguir leyendo eternamente por si viene algún 0 o un 1. Entonces la máquina extena se queda eternamente esperando a su máquina interna; es decir, no termina nunca de procesar CARGAR su input.

Esto que dices es falso porque creo que no estás teniendo en cuenta una cosa: en las máquinas de Turing la computación es local. Es decir, lo que haga una máquina en el paso siguiente depende exclusivamente de la casilla que este leyendo el cabezal y del estado interno de la máquina. Una máquina de Turing no lee primero toda la cinta y luego hace cosas (obviamente eso es imposible porque la cinta es infinita). Puede ser que esté programada para que en el estado inicial leyendo una casilla en blanco pase directamente al estado final (y entonces lo hará siempre cuando le des una cinta en blanco, pero también lo hará si le das una cinta con un millón de unos y la inicias leyendo una casilla en blanco). O puede ser que esté programada para que en el estado inicial empezando con una casilla en blanco pase a un estado \( q_1 \), y que la máquina en estado \( q_1 \) leyendo una casilla en blanco avance una casilla a la derecha y vuelva al estado \( q_1 \), y que en este estado \( q_1 \) cuando esté leyendo un 1 pase al estado final. Entonces si le empiezas con una cinta en blanco la máquina loopeará, pero igual lo hará si le das una cinta con un millón de 1's y la inicias en una casilla que esté a la derecha de todos ellos.

Citar
En las máquinas reales uno podría decir también: se queda esperando eternamente su input, es decir, se detiene. Pero eso es detectable, hay tercer estado que es no terminó de procesar ni loopeó. No tuvo input por timeout. En las MT una combinación de unos y ceros puede indicar "nulo", y mandarla a un estado que no es terminal. Es cuestión de definición, la suposición de Ivorra no es forzosa.

Insisto: las máquinas de Turing no tienen input tal como tú lo estás considerando, no es más que una convención de decir que el input de la función que computa es tal si se inicia la máquina con una cinta en tal configuración. Pero al margen de convenciones, la máquina de Turing no distingue en ningún caso si la cinta está inicialmente en una configuración o en otra, ella mira qué es lo que hay en la casilla en la que está (y únicamente en esa) y hace lo que le dice su programación. Si quieres pensarlo así, en una máquina de Turing el "input" (ahora entendido como los datos que toma en cuenta la máquina para decidir lo que va a hacer en el siguiente paso) en cada paso es únicamente la casilla en la que está y el estado interno de la máquina. Para una máquina de Turing no tiene ningún sentido "cargar" el input.

Saludos

14 Enero, 2012, 01:44 am
Respuesta #24

Elius

  • $$\Large \color{#5e8d56}\pi\,\pi\,\pi$$
  • Mensajes: 399
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
@Óscar
Todo lo que dices es sensato, pero estamos entrando en un terreno de disputas semánticas, acerca de qué significa "cargar", y qué es posible establecer como hipótesis y qué es forzoso.

Luego dices que el input no interesa, y allí ya no te sigo (¿interpreto mal?).

Creo que no conviene entrar en una discusión minuciosa de esto, porque si bien está todo relacionado, mi interés primario ahora (aunque luego apunte al HP) es mostrar que un algoritmo que ejecuta con su propio código como input, sea de Turing o en un lenguaje cualquiera de uso normal en la comunidad matemática e informática, no tiene tiene una terminación normal (un estado final), ni entra en un ciclo infinito, sino que en un momento dado se queda sin input. Que en ese mismo momento se le agreguen sentencias para que haga cualquier otra cosa, es otro tema, es otro programa.

Es cierto que estoy agregando condiciones, porque justamente estoy buscando el punto en el que se cumple lo que digo, qué condiciones son necesarias, para establecer que la autoaplicación es imposible. Luego alguien puede decir, "bueno, pero yo no tengo por qué aceptar esas condiciones", es cierto. Pero sabríamos qué límite se atraviesa cuando entramos en situaciones donde las  paradojas se transforman en teoremas.

Por ahora, veo que un programa universal que no tiene ciclos infinitos predeterminados (si le agrego "si falta el segundo argumento entonces loop forever" es como "plantar evidencia"), ni cadenas infinitas de llamados a funciones o procedimientos, y además tiene una cantidad fija de argumentos obligatorios, entonces si ejecuta como input su propio código termina con error por falta de argumentos. No creo que sea demasiado restrictivo.

En el caso de los algoritmos ejecutables por MTs, las cosas dependen tanto de las convenciones iniciales, que por ahora prefiero esperar a para ver cómo traducirlo a ese nivel de microinstrucciones donde sólo entran 1, 0, o blanco. Hay otras definiciones como las de Elliot Mendelson (tú lo conoces seguro) en donde se habla de "un conjunto finito de símbolos", no sólo esos tres, lo que haría más manejable el lenguaje. Los algoritmos y MT son como el código binario de las computadoras reales. Llega un momento que se demuestran cosas, pero por la complejidad del lenguaje no se puede mostrar ningún ejemplo (¿algun sumó 20 + 45 con MT de tres símbolos?).

De lo que creo estar seguro, es que si algo es cierto para un lenguaje de alto nivel, es cierto para su código compilado, y hay un equivalente en MT.

Saludos!




14 Enero, 2012, 01:49 am
Respuesta #25

argentinator

  • Consultar la FIRMAPEDIA
  • Administrador
  • Mensajes: 7,739
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
  • Vean mis posts activos en mi página personal
    • Mis posts activos (click aquí)
Citar
Luego dices que el input no interesa, y allí ya no te sigo (¿interpreto mal?).

Creo que no conviene entrar en una discusión minuciosa de esto,

Yo creo que sí habría que discutir esto,
porque una máquina de Turing tiene una definición concreta y exacta, la cual es capaz de despejar todo tipo de confusiones y ambigüedades.

Además, pienso que es un error confundir "máquinas reales" con "máquinas de Turing", pues las computadoras no pueden escribir en una cinta de longitud "ilimitada".

En cuanto a tus intentos de querer descartar de antemano aquellos algoritmos que entran en un loop, o cosas similares, en realidad eso es lo mismo que intentó hacer Turing.
Pero él demostró que un programa así no puede existir.

Si alguien intenta hacer una máquina universal que de antemano detecte si un programa cualquiera termina o no, necesariamente tiene que fracasar en su intento, pues es teóricamente imposible.


14 Enero, 2012, 02:05 am
Respuesta #26

Elius

  • $$\Large \color{#5e8d56}\pi\,\pi\,\pi$$
  • Mensajes: 399
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
En cuanto a tus intentos de querer descartar de antemano aquellos algoritmos que entran en un loop, o cosas similares, en realidad eso es lo mismo que intentó hacer Turing.
Pero él demostró que un programa así no puede existir.
Pero es que yo no intento descartar los algoritmos que EVENTUALMENTE puedan entrar en loop, sino aquellos que lo tienen codificado explícitamente:

while ( 1 == 1 ) {

            z=y;
}

o bien

f(){

         f();
}

Eso se puede hacer fácilmente.

Lo otro, lo imposible (ya ves que no estoy en contra de Turing globalmente, sólo de un pasito de su demostración) es encontrar en los algoritmos condiciones de looping ocultas, abarcando toda clase de algoritmos. Porque restringiendo la clase, se puede. Una manera muy tonta es ver que si un algoritmo no tiene ciclos (do while) ni goto, termina seguro. Que haga lo que debería es otro tema.

En cuanto a la discusión en lenguaje de microcódigo, no la descarto, sólo la postergo un poco hasta tener las cosas claras en lenguajes de alto nivel.

Saludos!


14 Enero, 2012, 02:10 am
Respuesta #27

Elius

  • $$\Large \color{#5e8d56}\pi\,\pi\,\pi$$
  • Mensajes: 399
  • País: ar
  • Karma: +0/-0
  • Sexo: Masculino
Veo que no tengo ningún aliado...

Ja ja ja, yo me la busco, ¿no?

Saludos!


14 Enero, 2012, 02:37 am
Respuesta #28

Óscar Matzerath

  • $$\Large \color{#c88359}\pi\,\pi\,\pi\,\pi$$
  • Mensajes: 567
  • Karma: +0/-0
  • Sexo: Masculino
Hola,

En general estoy de acuerdo en que hay toda una serie de conceptos que están definidos de manera bastante vaga en este asunto, y que por eso no se acaba de concretar nunca nada. De todas maneras en el asunto de las MT todo está perfectamente definido.

Sobre lo que el input no interesa en las máquinas de Turing, quiero decir que en vez de usar inputs en el sentido que siempre se ha estado usando hasta ahora (la máquina M tiene input n si empiezas con una cinta con n+1 unos y estás leyendo el 1 que está más a la derecha), puedes usar una codificación recursiva de todas las posibles configuraciones iniciales de la cinta (esto se puede hacer porque la cinta únicamente tiene escrita una porción finita, así que equivale a dar una codificación recursiva de todas las sucesiones finitas de 0's y 1's, cosa que se conoce bastante bien). Ahora una máquina de Turing siempre tiene un input en este sentido, empieces en la configuración que empieces, y o bien para o bien no para (siempre con la definición de Ivorra).

Sobre las definiciones de MT's más amplias (máquinas con un alfabeto finito cualquiera como mencionas, o MT's multicinta, etc) tienes toda la razón al afirmar que hacen mucho más manejable el asunto, y mucho más fácil hacer implementaciones prácticas de programas sencillos. Pero la contrapartida es que a definiciones más complejas y permisivas, más difíciles son de analizar desde el punto de vista teórico. Por eso todos estos temas de computabilidad se estudian con MT's y no con lenguajes de programación reales como C, y sin embargo se usa C para programar y no MT's o código binario. Así como las MT's son fáciles de analizar teóricamente, pues su definición es muy sencilla, ponte tú a a hacer las mismas demostraciones que se hacen en computabilidad teórica con C. Y viceversa, ponte tú a programar un programa sencillo en C con una MT, seguro que te pasas un buen rato (como el que dices de la suma). Esto es algo que pasa mucho: la utilidad práctica es inversamente proporcional a la complejidad del análisis teórico. De todas maneras, se puede demostrar (y es lo que se hace, no con C porque sería demasiado largo, pero sí con MT's con alfabetos arbitrarios o MT's multicinta) que todos estos conceptos son equivalentes, en cuanto a que pueden computar exactamente lo mismo, y así puedes usar lo que te interese en cada situación.

Saludos

14 Enero, 2012, 03:17 am
Respuesta #29

feriva

  • $$\Large \color{#a53f54}\pi\,\pi\,\pi\,\pi\,\pi\,\pi\,\pi$$
  • Mensajes: 11,339
  • País: es
  • Karma: +1/-0
  • Sexo: Masculino
[quote author=Elius link=topic=53523.msg213429#msg213429  Una manera muy tonta es ver que si un algoritmo no tiene ciclos (do while) ni goto, termina seguro. Que haga lo que debería es otro tema.



[/quote]

Creo que no, Elius, no sé, no sé. Pienso que el bucle no sería de programación, no se originaría, por así decirlo, en un sólo código fuente, sino entre las sentencias de ambos; sean cuales sean éstas, aunque sean simples definiciones de variables sin más (claro que esto sólo le afectaría al programa que ejecuta, el otro está parado, simplemente origina el bucle por confusión cuando el otro lo lee).
O sea, un ordenador empieza a ejecutar; luego al menos cambiará un bit en algún byte, por ejemplo -a voleo, no sé si esto sería una instrucción para empezar, pero da igual, no me acuerdo de memoria- el estado inicial del byte es 11001100 y para ejecutar tiene que pasar a ser 11001101, digamos. Este byte está alojado en una dirección concreta. Cuando el programa que ejecuta lee esta dirección respecto del programa pasivo, y desde el principio del código fuente, lee 11001100, y empieza el desbarajuste en búsqueda del ajuste; pero no puede llegar nunca porque el estado final de lo que está leyendo tiene que ajustarse con su estado; y es imposible, la cuestión está en que lo que lee le afecta, porque lo interpreta como otra cosa, y nunca puede llegar a un final -mismo orden en todos los bits y fin de la rutina- porque nunca termina de  ajustar el paso, ya que va a "contratiempo", diciéndolo con una expresión musical, uno ha empezado a cambiar antes que otro -esto hay que entenderlo, sólo cambia uno pero por efecto de los dos- y no pueden terminar juntos, con lo que programa que ejecuta no puede terminar porque por culpa de lo que lee no llega a ajustar su orden inicial (se había ocurrido un ejemplo con ciclos de permutaciones, pero no sé si sería apropiado del todo el ejemplo y no me atrevo a ponerlo) 
 Creo yo que eso es lo que pasaría con la máquina por dentro; lo que se viera por fuera en el monitor ya no sé   8^)

Saludos y buenas noches desde aquí.