Exámen 3 de diciembre 2002

Anuncio
Programación Avanzada (PAV)
Examen Parcial —3 de Diciembre de 2002—
Ejercicio 1 (Tema 2)
Obtener la forma plana (y, en su caso, reordenada) del hecho :
0.5 puntos
p(f(a),X,g(Y,X)).
Respuesta:
A1 = f(X4), X4 = a, A2 = X5, A3 = g(X6,X5)
y de la query :
?- p(Z,f(Z),g(a,b)).
Respuesta:
A1 = X4, A2 = f(X4), X5 = a, X6 = b, A3 = g(X5,X6)
Nota: se deben usar los registros de argumento A1,...,An. Recordad que las ecuaciones “eliminables” no
deben aparecer.
Ejercicio 2 (Tema 2)
1 punto
Obtener la secuencia de instrucciones asociada a la siguiente forma plana del hecho p(f(g(X)),Y,g(X)).:
A1 = f(X4), X4 = g(X5), A2 = X6, A3 = g(X5)
Respuesta:
100: p/3:
101:
102:
103:
get_structure f/1, A1
unify_variable X4
get_structure g/1, X4
unify_variable X5
104:
105:
106:
107:
get_variable X6, A2
get_structure g/1, A3
unify_value X5
proceed
Ejercicio 3 (Tema 3)
Completar la siguiente secuencia de instrucciones resultante de compilar el programa Prolog:
1.5 puntos
q(a).
r(s(b)).
p(X,Y) :- q(X), r(Y).
?- p(Z,s(Z)).
Respuesta:
100: q/1:
101:
102: r/1:
103:
104:
105:
106: p/2:
107:
108:
109:
get_structure a/0, A1
proceed
get_structure s/1, A1
unify_variable X2
get_structure b/0, X2
proceed
allocate 1
get_variable X3, A1
get_variable Y1, A2
put_value X3, A1
110:
call q/1
111:
put_value Y1, A1
112:
call r/1
113:
deallocate
114: query: allocate 0
115:
put_variable X3, A1
116:
put_structure s/1, A2
117:
set_value X3
118:
call p/2
119:
deallocate
1
Ejercicio 4 (Tema 3)
Dado el programa Prolog:
3 puntos
clave(a,b).
key(s(c)).
test(c(A,B,C)) :- clave(A,B), key(C).
?- test(X).
cuya secuencia de instrucciones asociada es:
100: clave/2: get_structure a/0,A1
101:
get_structure b/0,A2
102:
proceed
103: key/1: get_structure s/1,A1
104:
unify_variable X2
105:
get_structure c/0,X2
106:
proceed
107: test/1: allocate 1
108:
get_structure c/3, A1
109:
unify_variable X3
110:
unify_variable X4
111:
unify_variable Y1
112:
put_value X3,A1
113:
put_value X4,A2
114:
call clave/2
115:
put_value Y1,A1
116:
call key/1
117:
deallocate
118: query: allocate 0
119:
put_variable X2,A1
120:
call test/1
<--------- P
121:
deallocate
122: halt <------------------------ CP
realizad la ejecución de las instrucciones, comenzando en la instrucción apuntada por P y partiendo del
siguiente estado para HEAP, STACK y los registros (si los valores que hay escritos cambian, tachad el valor
actual y escribid el nuevo a la derecha):
X → 1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
HEAP
REF 1000
STR 1002
c/3
REF 1003
REF 1004
REF 1005
STR 1007
a/0
STR 1009
b/0
STR 1011
s/1
REF 1012
STR 1014
c/0
STR
STR
STR
STR
1002
1007
1009
1011
E → 2000
2001
2002
2003
2004
2005
2006
STACK
1997
122
0
2000
121
1
REF
1005
Registros Xi (Ai)
STR
1014
1
2
3
4
REF
REF
REF
REF
1000
1000
1003
1004
REF
REF
1003
1004
REF
REF
1005
1012
Señalad también la posición en memoria de la variable X y dad su valor al finalizar la ejecución:
X = c(a,b,s(c))
Nota: usad la versión “refinada” de bind
2
Ejercicio 5 (Tema 4)
Obtener la secuencia de instrucciones resultante de compilar el programa Prolog:
2 puntos
reverse(L,R) :- rev(L,nil,R).
rev(nil,Acc,Acc).
rev(list(H,T),Acc,R) :- rev(T,list(H,Acc),R).
?- reverse(L,R), reverse(R,NL).
Respuesta:
100: reverse/2: allocate 0
101:
get_variable X4,A1
102:
get_variable X5,A2
103:
put_value X4,A1
104:
put_structure nil/0,A2
105:
put_value X5,A3
106:
call rev/3
107:
deallocate
108: rev/3: try_me_else L1
109:
get_structure nil/0,A1
110:
get_variable X4,A2
111:
get_value X4,A3
112:
proceed
113: L1: trust_me
114:
allocate 0
115:
get_structure list/2,A1
116:
unify_variable X4
117:
unify_variable X5
3
118:
get_variable X6,A2
119:
get_variable X7,A3
120:
put_value X5,A1
121:
put_structure list/2,A2
122:
set_value X4
123:
set_value X6
124:
put_value X7,A3
125:
call rev/3
126:
deallocate
127: query: allocate 1
128:
put_variable X3,A1
129:
put_variable Y1,A2
130:
call reverse/2
131:
put_value Y1,A1
132:
put_variable X4,A2
133:
call reverse/2
134:
deallocate
Ejercicio 6 (Tema 4)
1 punto
En la compilación de las reglas empleamos la instrucción allocate cuyo objetivo es almacenar en el STACK los entornos
de activación de procedimiento. Dichos entornos almacenan tanto las variables permanentes del procedimiento como
el valor actual del registro CP. Considera, por ejemplo, el siguiente programa Prolog:
p(X,Y) :- q(X), r(Y).
--->
allocate 1
?- p(A,B), (*) otras_llamadas.
En este caso, la ejecución de la instrucción allocate tendrá como efecto almacenar en el STACK el valor de la
variable permanente “Y” ası́ como el valor del registro CP (que apuntará a la posición (*)). Sin embargo, parte de
esta información no es siempre necesaria. Completa el programa anterior con las definiciones para los procedimientos
“q” y “r” de forma que la instrucción allocate pueda eliminarse sin que se pierdan ni los valores de las variables
permanentes ni el valor correcto del registro CP. Si piensas que esto no es posible, explica porqué.
Respuesta:
No es posible. El motivo es que, independientemente de la definición de los procedimientos “q” y “r”, el
valor del registro CP siempre se perderá al ejecutar la instrucción call q/1.
Ejercicio 7 (Tema 4)
1 punto
Los programas recursivos pueden consumir una gran cantidad de memoria en tiempo de ejecución. Sin embargo, en
ciertos casos es posible mejorar esta situación mediante la optimización conocida como LCO (“Last Call Optimization”). Dicha optimización consiste, esencialmente, en liberar la memoria del STACK justo antes de realizar la última
llamada del procedimiento. Por ejemplo, dado el siguiente código:
p/1: allocate 0
get_variable X2,A1
put_value X2,A1
call p/1
deallocate
asociado a la cláusula “p(X) : −p(X)”, la optimización LCO generarı́a el siguiente código:
p/1: allocate 0
get_variable X2,A1
put_value X2,A1
deallocate
call p/1
(*)
(**)
Es decir, primero se elimina el entorno del STACK (*) y luego se realiza la última llamada del procedimiento (**). Sin
embargo, para que este cambio sea correcto, es necesario modificar ligeramente la definición de la instrucción call.
Indica cual deberı́a ser la nueva definición de la instrucción call para que funcione correctamente el ejemplo anterior.
Respuesta:
deallocate
≡
CP ← STACK[E + 1];
E ← STACK[E];
P ← P + instruction size(P);
call p/n
≡
num of args ← n;
P ← @(p/n);
4
Descargar