A. Semántica / Verificación de Programas 1. Existe algún programa

Anuncio
A. Semántica / Verificación de Programas
1. Existe algún programa en C para el cual no hay equivalente (semántico) en Prolog? O viceversa?
Explica brevemente tu respuesta.
Respuesta:
Church’s thesis: any computable function can be computed by a Turing machine.
2. Considera el siguiente programa en IMP donde inicialmente n ≥ 0. Encuentra un invariante para el loop
en el programa. Entre mas fuerte sea tu invariante, mas útil es (por ejemplo, true es un invariante para
cualquier loop, pero no es muy útil).
j := 0;
x := 1;
while j < n do
j := j + 1; x := 2 * x
Respuesta:
The loop invariant is
0 >= j and j =< n and x = 2^j
3. Nota que n (inicialmente n ≥ 0) no es modificado nunca en el programa de la pregunta anterior. Usando
el método de prueba de tripletas de Hoare, prueba que la propiedad x = 2n se satisface al terminar el
while loop (es decir, al terminar el programa). Es decir, prueba formalmente la tripleta:
{n≥0}
j := 0;
x := 1;
while j < n do
j := j + 1; x := 2 * x
{x:=2^n}
B. Programación Lógica
1. Considera el siguiente programa lógico:
m(X) :- s(X),
m(X) :- s(X),
s(X) :- l(X).
s(X) :- q(Y),
q(X) :- p(X).
p(b). r(a,b).
n(b).
n(X).
r(X,Y).
l(c). n(a).
Dibuja el arbol SLD completo para la pregunta ?- m(a)
1
2. Considera el siguiente programa en Prolog:
path(X,X).
path(X,Y) :- path(Z,Y) , link(X,Z).
link(s,c).
link(s,t).
Que respuestas obtenemos del interprete de Prolog si le preguntamos ?- path(s,T) y repetidamente
pedimos mas soluciones tecleando ‘;’ .
Respuesta:
?- path(simula67,T).
T = simula67 ;
T = cplusplus ;
T = smalltalk80 ;
Stack Overflow
3. El siguiente predicado de Prolog determina si existe un camino entre dos nodos de una gráfica dirigida
acíclica.
reach(X, Y) :- arc(X, Y).
reach(X, Y) :- arc(X, Z), reach(Z, Y).
Asume que arc(X,Y) es verdadero cuando existe un arco desde el nodo X al nodo Y. Si hacemos la
pregunta reach(a, b), la evaluación de Prolog simplemente nos dirá si existe un camino desde el nodo
a al nodo b.¿Como podemos aumentar la funcionalidad de reach(a,b) para que también nos regrese el
camino entre a y b (si es que existe alguno)?. Esto es, necesitas definir un predicado ternario
reach(X,Y,Path). La pregunta reach(a,b,P) debe fallar si no existe camino alguno entre a y b, y
en el caso contrario, debe tener éxito y regresarnos en P el camino entre a y b (como una lista en
Prolog).
Respuesta:
reach(X, Y, [X, Y]) :- arc(X, Y).
reach(X, Y, [X|Path]) :- arc(X, Z), reach(Z, Y, Path).
C. Programación Funcional
1. A que evalúa la siguiente expresión:
(fn g => g 3) (fn x => x * 2)
Respuesta:
(fn
->
->
->
g => g 3) (fn x => x * 2)
(fn x => x * 2) 3
3 * 2
6
2
2. Escribe definiciones en SML para las funciones
(a) lenght (longitud de una lista)
(b) append (concatenacion de 2 listas)
(c) usando tus definiciones rescribe paso a paso las expresiones length([10,20,30]) y
append [1,2] [3,4]
Respuesta:
fun length []
= 0
|
length (x::xs) = 1 + length(xs) ;
length([10,10,10])
-> 1 + length([10,10])
1 + 1 + length([10])
1 + 1 + 1 + length([])
1 + 1 + 1 + 0
3
fun append []
ys = ys
|
append (x::xs) ys = x :: (append xs ys);
append [1,2] [3,4]
-> append (1::2::nil) [3,4]
1::(append (2::nil) [3,4])
1::(2::(append [] [3,4])
1::(2::([3,4]))
[1,2,3,4]
3. Lenguajes funcionales como SML permiten al usuario definir tipos de datos recursivos. Por ejemplo, un
árbol binario de enteros puede ser definido por el tipo de datos
datatype IntBinTree =
Empty |
Node of (IntBinTree, int, IntBinTree) ;
Define una función postorden : IntBinTree → int list. Esta función toma un intBinTree como
argumento y regresa una lista de enteros. Esta lista contiene los enteros en el árbol binario; el orden de
estos enteros es el generado recorriendo el árbol en post orden: en un recorrido post orden de un árbol
cada nodo es visitado después de su subárbol izquierdo y derecho.
Respuesta:
fun postorder(Empty) = nil
| postorder(Node(t1,n,t2)) =
append(postorder(t1), append(postorder(t2), [n]));
fun append(nil, ys) = ys
| append(x::xs,ys) = x :: append(xs,ys);
3
D. Concurrencia
1. Considera el siguiente programa con dos procesos P1 y P2:
var v1, v2 of boolean;
initially v1=v2=false;
P1 is
repeat
v1:=true;
while v2 do no-op;
Critical_Section_1;
v1:=false;
Remainder_Section_1;
until false;
P2 is
repeat
v2:=true;
while v1 do no-op;
Critical_Section_2;
v2:=false;
Remainder_Section_2;
until false;
(a) El programa satisface la propiedad de exclusión mutua? Explica.
(b) El programa satisface la propiedad de progreso? Explica.
2. Usando semáforos como mecanismo de sincronización propón una solución al problema de los filósofos
comensales (dining philosophers).
Respuesta:
Philosopher i:
repeat
wait(chopstick[i])
wait(chopstick[i+1 mod 5])
…
eat
…
signal(chopstick[i]);
signal(chopstick[i+1 mod 5]);
…
think
…
until false;
3. Contrasta brevemente la operacion x.wait de un monitor con la operacion wait(s) asociada con los
semáforos.
E. Practicas
1. Escribe el predicado transfiere(N,A,B,I) del problema de las torres de Hanoi, donde:
•
•
•
•
N es el numero de discos a transferir
A es la estaca en donde los discos están
B es la estaca a donde queremos mover los discos
I es la estaca intermedia que usamos para almacenar discos
Asume (como en la practica) el predicado para mover los discos:
mueve(A,B) :nl, write('Mueve el disco de arriba desde '),
write(A), write(' a '), write(B).
4
Respuesta:
transfiere(1,A,B,I) :- mueve(A,B).
transfiere(N,A,B,I) :- M is N-1, transfiere(M,A,I,B),
move(A,B), transfiere(M,I,B,A).
2. Escribe la definicion del predicado encodeestatement para compilar el ifthenelse (asume ya
definidas encodetest y encodestatment para los otras instrucciones del lenguaje). Es decir, define
encodestatement(if(Test,Then,Else),D,(Testcode; Thencode; instr(jump,L2);
label(L1); Elsecode; label(L2)) ) :-…
Respuesta:
encodestatement(if(Test,Then,Else),D,
(Testcode; Thencode; instr(jump,L2); label(L1); Elsecode; label(L2)) ) :encodetest(Test,D,L1,Testcode),
encodestatement(Then,D,Thencode),
encodestatement(Else,D,Elsecode).
3. Escribe la definicion de assemble/3. Recuerda que el significado de assemble(X,Y,Z) es que Y es
la dirección de inicio y Z la ultima dirección de la secuencia de instrucciones X. Recuerda que el
contexto donde assemble aparece es el predicado compile:
compile(Source, (Code; instr(halt,0); block(L)) ) :encodestatement(Source,D,Code),
assemble(Code,1,N0),
N1 is N0+1,
allocate(D,N1,N),
L is N-N1.
La definicion de assemble es algo asi:
assemble((Code1;Code2),N0,N1) :- …
assemble(instr(_,_),N0,N) :- …
assemble(label(N),N,N).
assemble((Code1;Code2),N0,N1) :- assemble(Code1,N0,N2), assemble(Code2,N2,N1).
assemble(instr(_,_),N0,N) :- N is N0+1.
assemble(label(N),N,N).
5
Descargar