Universidad Simón Bolívar Departamento de Computación y Tecnología de la Información CI2612 – Algoritmos y Estructuras II Abril-Julio 2011 Carnet: Nombre: Examen II (35 puntos) Antes de empezar, revise bien el examen, el cual consta de 3 (tres) preguntas. Pregunta 0 Pregunta 1 Pregunta 2 Total 8 puntos 10 puntos 17 puntos 35 puntos Pregunta 0 - 8 puntos En relación con los textos sobre tipos abstractos de datos (TADs) recomendados en el curso, responda las siguientes preguntas: (0.0) En el texto de Barbara Liskov (con John Guttag), “Program Development in Java – Abstraction, Specification, and Object-Oriented Design”, la autora sugiere que la “abstraction function” y la “representation invariant” sean implementadas para mejorar la confiabilidad de los programas. Explique muy brevemente qué son estas dos componentes y cómo sugiere Liskov implementarlas. (0.1) En el texto de Richard Mitchell, “Abstract Data Types and Modula-2”, el autor utiliza el lenguaje OBJ además de otros. Explique qué tipo de lenguaje es OBJ e indique cuáles TADs son trabajados por Mitchell con este lenguaje. (0.2) Continuando con el texto de Richard Mitchell, el autor sugiere tres posibilidades para llevar operaciones de la especificación de un TAD hacia subrutinas de una implementación. Explique dos de ellas. Pregunta 1 - 10 puntos En esta pregunta trabajaremos con un tipo abstracto de datos (TAD) para multiconjuntos, cuyos elementos serán de algún tipo cualquiera T , con la restricción de que se debe disponer de una relación de orden total “v” sobre T . Para implementar el TAD, se decide utilizar un arreglo ordenado como estructura de datos. A continuación se presentan una especificación de este TAD con modelo abstracto con sólo una de sus operaciones y la re-especificación correspondiente del TAD con el modelo concreto propuesto: Especificación A de TAD MultiCjto (T ) Modelo de Representación const tmax : int var m : bag (T ) Invariante de Representación tmax > 0 ∧ # m 6 tmax Operaciones .. . proc intersectar ( in-out a : MultiCjto ; in b : MultiCjto ) { Pre : true } { Post : a.m = a 0 .m ∩ b.m } .. . Fin TAD Especificación B de TAD MultiCjto (T ) , refinamiento de A Modelo de Representación const tmax : int var elems : array [ 0..tmax ) of T tam : int Invariante de Representación tmax > 0 ∧ 0 6 tam 6 tmax ∧ ( ∀ i, j : 0 6 i < j < tam : elems[i] v elems[j] ) Relación de Acoplamiento m = bb i : 0 6 i < tam : elems[i] cc Operaciones .. . proc intersectar ( in-out a : MultiCjto ; in b : MultiCjto ) { Pre : true } { Post : bb i : 0 6 i < a.tam : a.elems[i] cc = bb i : 0 6 i < a 0 .tam : a 0 .elems[i] cc ∩ bb i : 0 6 i < b.tam : b.elems[i] cc } .. . Fin TAD En las especificaciones presentadas, consideramos que el operador unario # da la cantidad de elementos de un multiconjunto. También consideramos que la operación de intersección de multiconjuntos corresponde a la definición dada por Morgan en la referencia bibliográfica recomendada para este curso, que toma la cantidad mínima de ocurrencias de cada elemento. Por ejemplo: bb 2, 2, 4, 5, 8, 8, 8 cc ∩ bb 2, 3, 3, 4, 4, 8, 8 cc = bb 2, 4, 8, 8 cc . Se desea entonces, específicamente, que Ud. implemente la operación intersectar de la especificación B con modelo concreto. Su solución debe ser iterativa, y debe indicar cota variante de terminación de toda iteración que utilice. No hace falta que indique invariantes de sus iteraciones. Note que una buena manera de implementar esta operación se logra mediante una variante del auxiliar mezclar del algoritmo de ordenamiento por mezcla, por lo que se exige que su implementación tenga tiempo de ejecución cuyo peor caso sea de complejidad O (a.tam + b.tam) . Pregunta 2 - 17 puntos En esta pregunta trabajaremos con un tipo abstracto de datos (TAD) para colas, cuyos elementos serán de algún tipo cualquiera T . A continuación se presenta una especificación de este TAD con modelo abstracto basado en una secuencia de tamaño acotado. Las operaciones sobre secuencias que se utilizan en la especificación son las del texto de Morgan recomendado como referencia bibliográfica para este curso. Especificación A de TAD Cola (T ) Modelo de Representación const tmax : int var contenido : seq (T ) Invariante de Representación tmax > 0 ∧ # contenido 6 tmax Operaciones proc vacia ( out c : Cola ) { Pre : true } { Post : c.tmax > 0 ∧ c.contenido = h i } proc encolar ( in-out c : Cola ; in e : T ) { Pre : # c.contenido < c.tmax } { Post : c.contenido = c0 .contenido ++ hei } proc desencolar ( in-out c : Cola ) { Pre : c.contenido 6= h i } { Post : c.contenido = tl (c0 .contenido) } proc primero ( in c : Cola ; out e : T ) { Pre : c.contenido 6= h i } { Post : e = hd (c.contenido) } proc esVacia ( in c : Cola ; out v : boolean ) { Pre : true } { Post : v ≡ (c.contenido = h i) } Fin TAD Continúa. . . Para la implementación de nuestro TAD, utilizaremos arreglos de manera análoga a la implementación de colas mediante arreglos presentada en el texto de Cormen et al. que utilizamos como referencia bibliográfica en este curso. Note que en esta implementación el arreglo es declarado de tamaño tmax +1 , desperdiciándose así una casilla de éste. La nueva especificación del TAD con el modelo concreto propuesto basado en arreglos sería la siguiente: Especificación B de TAD Cola (T ) , refinamiento de A Modelo de Representación const tmax : int var a : array [ 0..tmax +1 ) of T inic, fin : int Invariante de Representación tmax > 0 ∧ 0 6 inic 6 tmax ∧ 0 6 fin 6 tmax Relación de Acoplamiento ( inic 6 fin ⇒ contenido = h i : inic → fin • a[i] i ) ∧ ( inic > fin ⇒ contenido = h i : inic → tmax +1 • a[i] i ++ h i : 0 → fin • a[i] i ) Operaciones proc vacia ( out c : Cola ) { Pre : true } { Post : c.tmax > 0 ∧ c.inic = 0 ∧ c.fin = 0 } proc encolar ( in-out c : Cola ; in e : T ) { Pre : c.inic 6= (c.fin + 1) mod (c.tmax +1) } { Post : c.a = c0 .a(c0 .fin : e) ∧ c.inic = c0 .inic ∧ c.fin = (c0 .fin + 1) mod (c.tmax +1) } proc desencolar ( in-out c : Cola ) { Pre : c.inic 6= c.fin } { Post : . . . } proc primero ( in c : Cola ; out e : T ) { Pre : c.inic 6= c.fin } { Post : e = c.a[c.inic] } proc esVacia ( in c : Cola ; out v : boolean ) { Pre : true } { Post : v ≡ (c.inic = c.fin) } Fin TAD Recuerde que en la notación utilizada por Morgan para definición de secuencias por comprensión, teniendo a x como variable generadora, teniendo enteros n y m, y teniendo una expresión E sobre x, la expresión h x : n → m • E i define la secuencia resultante de tomar valores en orden para x del rango [ n..m ) y obtener elementos para la secuencia a partir de la expresión E. Así, por ejemplo, tenemos que h x : 2 → 5 • x2 i = h 4, 9, 16 i y que h x : 1 → 5 • −x i = h −1, −2, −3, −4 i . Continúa. . . Basándose entonces en las especificaciones anteriores, responda las siguientes preguntas: (2.0) Complete la postcondición de la operación desencolar en la especificación B con modelo concreto. (2.1) Dé una implementación para la operación encolar de la especificación B con modelo concreto. (2.2) Demuestre formalmente que las postcondiciones de la operación esVacia en las dos especificaciones se corresponden adecuadamente, según la noción de refinamiento de datos. Ayuda – Le puede resultar útil la siguiente propiedad de “secuencia por comprensión vacía”: n6m ⇒ ( h x : n→m • E i = h i ≡ n = m ) , con variable generadora x cualquiera, enteros n y m cualesquiera, y expresión E cualquiera. También le puede resultar útil la siguiente propiedad de “concatenación vacía de secuencias”: s0 + + s1 = h i ≡ s0 = h i ∧ s1 = h i , con s0 y s1 secuencias cualesquiera. (2.3) En la implementación propuesta en el texto de Cormen et al., recién presentada en la especificación B, se desperdicia una casilla del arreglo al declararlo con tamaño tmax +1. La razón por la que se desperdicia una casilla es para evitar que se confundan las situaciones de “cola vacía” y “cola llena”. Esto se debe a que, de contar sólo con tmax casillas, al llenarse la cola con tmax elementos el índice fin volvería a alcanzar al índice inic, esto es, ambos índices volverían a ser iguales como cuando no hay ningún elemento en la cola. De allí que Cormen et al. opten por tener un arreglo con una casilla de exceso para diferenciar las dos situaciones extremas. Sin embargo, hay otra manera de diferenciar las situaciones extremas sin necesidad de la casilla de exceso, que es teniendo un atributo booleano que indique si la cola está llena o no. Esto correspondería a tener el siguiente nuevo modelo concreto: const tmax : int var a : array [ 0..tmax ) of T inic, fin : int llena : boolean en el que no hay casilla de exceso pero se tiene un nuevo atributo booleano. Indique parcialmente qué le cambiaría al resto de la especificación con modelo concreto, señalando específicamente lo siguiente: qué le agregaría al invariante de representación y cómo cambiaría la relación de acoplamiento.