Algoritmos y Estructuras de Datos I Tipos compuestos Observadores

Anuncio
Tipos compuestos
I
Algoritmos y Estructuras de Datos I
cada valor de un tipo básico representa un elemento atómico e
indivisible
I
I
I
Segundo cuatrimestre de 2015
I
I
Departamento de Computación - FCEyN - UBA
I
Clases teóricas - clase 4
un valor de un tipo compuesto contiene información que
puede ser dividida en componentes de otros tipos
ya vimos dos ejemplos de tipos compuestos:
I
Especificación de Tipos compuestos
I
I
Int
Float
Bool
Char
secuencias
tuplas
para definir un tipo compuesto, tenemos que darle
I
I
I
un nombre
uno o más observadores
condiciones invariantes
1
Observadores
I
2
Observadores
funciones que se aplican a valores del tipo compuesto y
devuelven el valor de sus componentes (pueden tener más
parámetros)
I
los observadores definen el tipo compuesto
I
I
I
Ejemplo: Tipo Punto
I
I
I
I
sus elementos representan puntos en el plano
componentes: coordenadas (x e y )
un observador para obtener cada una
I
los observadores pueden tener precondiciones
I
Definición:
tipo Punto {
observador X (p : Punto) : Float;
observador Y (p : Punto) : Float
}
3
si dos términos del tipo dan el mismo resultado para todos los
observadores, entonces se los considera iguales
esta condición define la igualdad == para tipos compuestos
(el operador == existe en todos los tipos)
si vale la precondición, no pueden devolver un valor indefinido
I
los observadores no tienen poscondiciones propias
I
si hay condiciones generales que deben cumplir los elementos
del tipo, se las presenta como invariantes de tipo
4
Más sobre el tipo Punto
I
Tipo Cı́rculo
Ejemplo: Especificación de un problema que recibe dos
números reales y construye un punto con esas coordenadas:
problema nuevoPunto(a, b : Float) = res : Punto {
asegura X (res) == a;
asegura Y (res) == b;
}
I
Cuando el resultado es de un tipo compuesto, usamos los
observadores para describir el resultado
I
Ejemplo: Función auxiliar para calcular la distancia entre dos
puntos
aux dist(p, q : Punto) : Float = (X (p) − X (q))2 + (Y (p) − Y (q))2
Sus elementos representan cı́rculos en el plano, formados por un
Punto que es su centro, y un real positivo que es su radio.
1/2
6
5
Tipo Cı́rculo
Invariantes de tipo
Un invariante de tipo es una expresión booleana que relaciona los
observadores del tipo, y es verdadera para cada elemento del tipo.
I
sus componentes son de tipos distintos
Un invariante de tipo
I Da condiciones que deben cumplir todos los elementos de un
tipo compuesto.
I Al especificar un tipo damos explı́citamente los invariantes de
tipo.
I Al observar un elemento de un tipo compuesto
está garantizado que se cumplen los invariantes.
I Al construir un elemento de un tipo compuesto tendremos que
asegurar que se cumplan los invariantes.
tipo Cı́rculo {
observador Centro(c : Cı́rculo) : Punto;
observador Radio(c : Cı́rculo) : Float;
invariante Radio(c) > 0;
}
I
el invariante del tipo especifica las condiciones que deben
cumplir entre sı́ los valores obtenidos por los observadores
para cualquier elemento del tipo
I
es la garantı́a de que los elementos estarán bien construidos
tipo T {
observador . . . ;
..
.
invariante R(x); }
7
8
Invariantes de tipo
I
Tipo Cı́rculo
los problemas que reciben valores del tipo compuesto como
argumentos pueden suponer que se cumplen los invariantes
I
Ejemplo: Especificar el problema de construir un cı́rculo a
partir de su centro y su radio:
problema nuevoCı́rculo(c : Punto, r : Float) = res : Cı́rculo {
requiere r > 0;
asegura (Centro(res) == c ∧ Radio(res) == r );
tipo T {
observador . . . ;
..
.
}
invariante R(x); }
I
problema probA(. . . , x : T, . . . ) = . . . {
requiere . . . ∧ R(x) ∧ . . . ;
| {z }
Ejemplo: Especificar el problema de construir un cı́rculo a
partir de su centro y un punto sobre la circunferencia:
problema nuevoCı́rculoPuntos(c, x : Punto) = res : Cı́rculo {
requiere dist(c, x) > 0;
asegura (Centro(res) == c ∧ Radio(res) == dist(c, x));
no hace falta
asegura . . . ;
}
}
9
10
Tipo MatrizhT i
Tipos genéricos
I
I
I
en los ejemplos vistos, cada componente es de un tipo
determinado de antemano
I
I
su contenido van a ser valores no siempre del mismo tipo
comportamiento uniforme
se llaman tipos genéricos o tipos paramétricos
I
I
tipo MatrizhT i {
observador filas(m : MatrizhT i) : Int;
observador columnas(m : MatrizhT i) : Int;
observador val(m : MatrizhT i, f , c : Int): T {
requiere 0 ≤ f < filas(m);

requiere 0 ≤ c < columnas(m);
precondición del observador

}
invariante filas(m) > 0;
invariante columnas(m) > 0;
}
también hay tipos compuestos que representan una estructura
I
tipo genérico de las matrices cuyos elementos pertenecen a un
tipo cualquiera T
definen una familia de tipos, y cada elemento de la familia es
una instancia del tipo genérico
los problemas que usen un tipo genérico definen una familia
de problemas
I
11
ejemplo: una instancia del tipo genérico MatrizhT i es
MatrizhChari
12
Operaciones genéricas con matrices
I
Operaciones sobre matrices para tipos instanciados
I
expresión que cuenta la cantidad de elementos de una matriz
aux suma(m : MatrizhInti) : Int =
P
[val(m, i, j) | i ← [0..filas(m)), j ← [0..columnas(m))];
aux elementos(m : MatrizhT i) : Int = filas(m) ∗ columnas(m);
I
expresión que suma los elementos de una matriz de enteros
especificación del problema de cambiar el valor de una
posición de una matriz
I
problema cambiar(m : MatrizhT i, f , c : Int, v : T ) {
requiere 0 ≤ f < filas(m);
requiere 0 ≤ c < columnas(m);
modifica m;
asegura filas(m) == filas(pre(m));
asegura columnas(m) == columnas(pre(m));
asegura val(m, f , c) == v ;
asegura (∀i ← [0..filas(m)))
asegura (∀j ← [0..columnas(m)), ¬(i == f ∧ j == c))
asegura val(m, i, j) == val(pre(m), i, j)));
}
especificación del problema de construir la matriz identidad de
n × n:
problema matId(n : Int) = ident : MatrizhInti {
requiere n > 0;
asegura filas(ident) == columnas(ident) == n;
asegura (∀i ← [0..n)) val(ident, i, i) == 1;
asegura (∀i ← [0..n))(∀j ← [0..n), i 6= j) val(ident, i, j) == 0;
}
I
I
I
¿importa el orden?
sı́; si estuviera al revés, se podrı́a indefinir val(ident, i, i)
en este caso, se indefinirı́a la poscondición, valiendo la
precondición
14
13
El tipo SecuenciahT i
Tuplas
I
I
ya lo usamos con su nombre alternativo: [T ]
I
presentamos también sus observadores: longitud e indexación
tipo ParhA, Bi{
observador primero(p : Par hA, Bi) : A
observador segundi(p : Par hA, Bi) : B
}
tipo SecuenciahT i {
observador long (s : SecuenciahT i) : Int;
observador ı́ndice(s : SecuenciahT i, i : Int) : T {
requiere 0 ≤ i < long (s); −→ precondición de observador
}
invariante long(s) ≥ 0;
}
I
tipo TernahA, B, C i{
observador primero(p : TernahA, B, C i) : A
observador segundo(p : TernahA, B, C i) : B
observador tercero(p : TernahA, B, C i) : C
}
notaciones alternativas
I
I
secuencias de longitud fijo, en las que cada elemento puede
pertenecer a un tipo distinto (predeterminado de antemano)
|s| para la longitud
si o s[i] para la indexación
I
Notación:
1. ParhA, Bi también se puede escribir (A, B)
2. TernahA, B, C i también se puede escribir (A, B, C )
15
16
Descargar