Codificación de programas. STP y SNAP Marı́a Emilia Descotte 3 de septiembre de 2014 Ejercicio 1. Se dice que un programa P en el lenguaje S respeta sus entradas si no tiene · 1 para ningún i (ni etiquetadas ni no etiinstrucciones del tipo Xi ← Xi + 1 ni Xi ← Xi − quetadas). Demostrar que el conjunto {#P | P respeta sus entradas} es un conjunto primitivo recursivo. Entendiendo el enunciado: ¿Qué significa que un programa respete sus entradas? Que en su código no hay ninguna instrucción de las que le modifican el valor a las variables de entrada. Si miramos los siguientes programas P y Q por ejemplo, P respeta sus entradas pero Q no. P : Y ←Y +1 Q : X1 ← X1 + 1 IF X2 6= 0 GO TO L ·1 X1 ← X1 − Y ←Y +1 Observamos que respetar las entradas es una propiedad del programa y no de la función que computa. Lo que nos piden es probar que el predicado p que dado un número natural devuelve un 1 si el programa con ese número respeta sus entradas y un 0 si no, es primitivo recursivo. Idea para resolver el ejercicio: Si pudiéramos mirar el código del programa, ¿cuál serı́a una forma ordenada de fijarnos si el programa respeta sus entradas o no? Podrı́amos ir mirando instrucción por instrucción hasta llegar a la última y fijarnos en cada · 1. Si alguna es de ese tipo, concluiremos que una si es del tipo Xi ← Xi + 1 o Xi ← Xi − el programa no respeta sus entradas y si llegamos al final sin encontrar ninguna de ese tipo concluiremos que sı́ las respeta. El problema es que no tenemos el código del programa sino su número. ¿Cómo pasamos del número de un programa a la información del código? ¡Con la codificación de programas vista en la clase teórica!: Codificamos a la instrucción I con #(I) = ha, hb, cii donde 1. si I tiene etiqueta L, entonces a = #(L); si no a = 0 2. si la variable mencionada en I es V entonces c = #(V ) − 1 3. si la instrucción I es (a) V ← V entonces b = 0 (b) V ← V + 1 entonces b = 1 (c) V ← V − 1 entonces b = 2 (d) IF V 6= 0 GOTO L0 entonces b = #(L0 ) + 2 Un programa P es una lista (finita) de instrucciones I1 , . . . , Ik Codificamos al programa P con #(P ) = [#(I1 ), . . . , #(Ik )] − 1 Luego para pasar del número a la información del código, vamos a necesitar observadores de pares y de listas que son p.r. y eventualmente sumar o restar algún numerito que también es p.r. Además, para describir la condición que debemos chequear, vamos a necesitar un ∀ acotado por la longitud del programa que en definitiva termina siendo como tomar longitud de una lista (todo p.r.) y decir algo ası́ como que si el número de la instrucción que estoy mirando es 1 o 2 entonces el número de la variable que involucra es impar por ejemplo. También parece que lo vamos a poder escribir como algo p.r. Juntando todo: Escribamos entonces el predicado en cuestión de manera que podamos justificar que es primitivo recursivo: ∀1≤i≤|x+1| l(r(x + 1[i])) = 1 ó l(r(x + 1[i])) = 2 → r(r(x + 1[i])) + 1 es impar Ejercicio 2. Demostrar que la siguiente función es parcial computable: f (x, y) = 1 ↑ (1) si para alguna entrada x1 y algún momento t de la ejecución de Φx , la variable Y tiene un valor mayor al de y caso contrario Entendiendo el enunciado: Necesitamos o bien escribir un programa que compute esta función o bien describirla de alguna otra manera en la cual sólo usemos cosas que sabemos que son parciales computables. Idea para resolver el ejercicio: Escribir un programa hecho y derecho suena medio tedioso. Tratemos de usar cosas que ya sepamos que son parciales computables. Nos habla de lo que pasa con una variable en cierto momento de la ejecución de un programa, ¿qué herramienta tenemos para hablar de lo que pasa en cierto momento de la ejecución de un programa? ¡El predicado SNAPSHOT visto en la clase teórica! Recordemos que SN AP (n) (x, e, t) = hnro de instrucción, lista representando el estadoi al momento t de la ejecución del programa con número e con entradas x. Recordando esto, es claro que f (x, y) = 1 sii existen x1 y t tales que r(SN AP (1) (x1 , x, t))[1] > y y se indefine sino. r(SN AP (1) (x1 , x, t))[1] > y es todo computable y no hay problema. Y adelante de eso aparecieron unos existenciales no acotados. Sabı́amos que los existenciales acotados eran p.r. pero también es cierto que los existenciales no acotados sobre predicados computables son parciales computables (Ejercicio si no lo vieron en la teórica). El problema es que como, en principio, sólo podemos tomar existenciales sobre cosas totales, no podemos anidarlos ası́ nomás porque el existencial justamente se indefine cuando no se cumple nunca la cláusula y en nuestro caso habı́a dos anidados. ¿Cómo hacemos para meter dos parámetros en uno sólo? ¡Con la codificación de pares! Solución: Luego podemos pensar que f (x, y) = 1 sii ∃ z tal que r(SN AP (1) (l(z), x, r(z)))[1] > y, donde el ∃ se define como 1 si el predicado de adentro se cumple e indefinido sino y, por lo tanto, f es parcial computable.