Método Algebraico de Especificación.

advertisement
Capı́tulo 3
Método Algebraico de
Especificación.
Los lenguajes de programación proporcionan habitualmente una signatura básica que
incluye los universos siguientes: BOOLEAN, CARDINAL, INTEGER, REAL y CHAR,
junto con las operaciones necesarias para poder trabajar con los valores de cada uno
de ellos —cuyas propiedades son bien conocidas—, ası́ como ciertos esquemas (enumeración, subrango, registro, tabla, conjunto) cuya instanciación permite ampliar el
número de universos y operaciones (procedimientos) disponibles en un programa. Los
datos de estos universos se representan de alguna forma y, en general, se puede suponer que cada programa opera sobre los elementos de un álgebra, correspondiente a las
representaciones concretas de valores y operaciones que existen en la máquina donde
se ejecuta el programa, que se comportan como los valores a los que representan.
Si embargo, siguiendo las orientaciones del diseño descendente, los programas se
deben diseñar de manera que los datos y las operaciones representen valores y operaciones abstractos de universos próximos a los dominios de los problemas o tareas
que abordan para poder aplicar los razonamientos propios de dichos dominios. Para esto es preciso disponer de representaciones adecuadas que se comporten como los
correspondientes entes abstractos, y para conseguir esto necesitamos primero, una caracterización lo suficientemente completa del comportamiento de los entes abstractos
que permita después, su adecuada representación.
Los valores abstractos de los universos de datos y las operaciones que se pretende
representar en un programa se puede suponer que también constituyen un álgebra, y
una de las formas más extendida para caracterizar o especificar álgebras se basa en el
uso de ecuaciones para expresar los comportamientos de valores y funciones.
3-43
3-44
3.1
CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN.
Construcción de una especificación
Para facilitar la especificación de álgebras correspondientes a los distintos universos
de datos que se utilizan en la programación utilizaremos relaciones de igualdad entre
términos y relaciones de pertenencia de términos a universos que se interpretarán de
la forma acostumbrada sobre las álgebras, y nos servirán para definir los resultados
de operaciones y también relaciones de contenido entre universos. En su forma más
general estas relaciones pueden estar condicionadas por otras ecuaciones o relaciones
de pertenencia, sin condicionar.
Para especificar álgebras, se enuncia su correspondiente signatura dando los nombres de los distintos universos de términos (tipos de datos) que intervienen y los nombres
de las distintas operaciones junto con sus dominios y recorridos (perfiles), y después,
se establece el comportamiento de cada operación mediante ecuaciones y/o relaciones
de pertenencia de la forma
(∀i ∈ [1..n] · ui = vi ) ∧ (∀j ∈ [1..m] · wj : sj ) ⇒ t = t0
(∀i ∈ [1..n] · ui = vi ) ∧ (∀j ∈ [1..m] · wj : sj ) ⇒ t : s,
con n ≥ 0 y m ≥ 0 y todas las variable tipificadas, que son las únicas relaciones
permitidas en el método algebraico que vamos a utilizar. Veamos un ejemplo.
Ejemplo 3.1 Una especificación para álgebra de valores lógicos se podrı́a dar de la
siguiente forma:
Universo
Booleanos .
Funciones
v : -> Booleanos .
f : -> Booleanos .
not_ : Booleanos -> Booleanos .
_and_ : Booleanos Booleanos -> Booleanos .
_or_ : Booleanos Booleanos -> Booleanos .
Axiomas
not v = f .
not f = v .
X:Booleanos => not (not X) = X .
X:Booleanos => X and v = X .
X:Booleanos => X and f = f .
X,Y:Booleanos => X and Y = Y and X .
X,Y,Z:Booleanos => (X and Y) and Z = X and (Y and Z) .
X:Booleanos => X or v = v .
X:Booleanos => X or f = X .
X,Y:Booleanos => X or Y = Y or X .
3.2. SIGNIFICADO DE UNA ESPECIFICACIÓN
3-45
X,Y,Z:Booleanos => (X or Y) or Z = X or (Y or Z) .
X,Y,Z:Booleanos => X and (Y or Z) = (X and Y) or (X and Z) .
X,Y,Z:Booleanos => X or (Y and Z) = (X or Y) and (X or Z) .
X,Y:Booleanos => not(X and Y) = (not X) or (not Y).
3.2
Significado de una especificación
La especificación del ejemplo anterior, en principio, es válida para cualquier álgebra
donde se cumplan sus ecuaciones, en particular, sirve para un álgebra con un solo
dominio que tenga un único elemento que sea a la vez interpretación de v y de f y,
también, para un álgebra A con un único dominio que tenga tres elementos, dos que
sirvan como interpretación de v y de f respectivamente y un tercer elemento r que se
comporte en la forma notA r = r, r andA r = r y r orA r = r. Para descartar modelos
como estos se introducen dos restricciones sobre los modelos a los que deben referirse
las especificaciones:
• Todo elemento de un dominio debe representar el valor de algún término construido con las funciones de la especificación, con lo que se excluyen modelos con
más elementos de los necesarios y además, permite descargar las especificaciones
porque determinadas propiedades pasan a ser demostrables por inducción sobre
la estructura de los términos. A los modelos que tienen esta propiedad se les
llama modelos generados por términos.
• Dos términos distintos que se puedan construir a partir de la signatura de la
especificación deben representar elementos distintos del álgebra, salvo que se
pueda demostrar a partir de los axiomas que deben ser iguales. De esta forma se
hace innecesario el uso de desigualdades para diferenciar términos. Los modelos
con esta caracterı́stica son modelos sin confusión de términos.
• Cuando se conjugan las dos condiciones anteriores se obtienen los modelos iniciales. Estos modelos se caracterizan porque son modelos generados por términos
con el mayor número de términos distintos; además, todos los modelos iniciales
son equivalentes (isomorfos).
Una vez adoptadas estas condiciones, sólo hay que preocuparse de establecer el
mı́nimo número de igualdades entre términos (generalmente relativas a resultados de
operaciones) y relaciones de pertenencia (normalmente para declarar que ciertos universos están contenidos en otros o que ciertas operaciones producen resultados de ciertos universos) que sean necesarias para tener una especificación consistente (libre de
contradicciones) y completa (que recoja todos los comportamientos esperados). Las especificaciones de este tipo donde no se niegan relaciones se denominan especificaciones
positivas.
3-46
CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN.
Para razonar con ecuaciones y con relaciones de pertenencia debemos incorporar a
nuestro sistema deductivo reglas especı́ficas para tratar con los predicados de igualdad
y de pertenencia. Para una especificación con un conjunto de axiomas Γ, estas reglas
son
Γ`t=t
(Reflexividad)
Γ ` t = t0
Γ ` t0 = t
(Simetrı́a)
Γ ` t = t0 ; Γ ` t0 = t00
Γ ` t = t00
(Transitividad)
Γ ` t1 = t01 ; · · · ; Γ ` tn = t0n
Γ ` f (t1 , · · · , tn ) = f (t01 , · · · , t0n )
(Conguencia)
Para cada fórmula de Γ:
(∀i ∈ [1..n] · ui = vi ) ∧ (∀j ∈ [1..m] · wj : sj ) ⇒ t = t0
Γ ` ∀i ∈ [1..n] · ui σ = vi σ; Γ ` ∀j ∈ [1..m] · wj σ : sj
Γ ` tσ = t0 σ
(Aplicación I)
Para cada fórmula de Γ:
(∀i ∈ [1..n] · ui = vi ) ∧ (∀j ∈ [1..m] · wj : sj ) ⇒ t : s
Γ ` ∀i ∈ [1..n] · ui σ = vi σ; Γ ` ∀j ∈ [1..m] · wj σ : sj
Γ ` tσ : s
(Aplicación II)
siendo t, t0 , t00 , ui , vi y wj términos y σ una sustitución. Y cuando se consideran sólo
modelos generados por términos, para que el sistema deductivo sea completo hay que
añadir una regla conocida como inducción estructural que permite deducir ecuaciones
y pertenencias que se cumplen sólo en estos modelos. Esta regla se enuncia
Γ ` ∀t ∈ TΣ,s · (∀t0 ∈ TΣ,s · (t0 ≺ t ⇒ P (t0 )) ⇒ P (t))
Γ ` ∀t ∈ TΣ,s · P (t)
para todos los términos de un cierto universo s ordenados por la relación
t0 ≺ t ⇔def t0 es un subtérmino propio de t
que es un preorden con la propiedad de que ninguna secuencia de términos estrictamente decreciente puede ser infinita1 , y para una propiedad P (t) expresada como una
fórmula basada en las relaciones de igualdad y de pertenencia, y establece que dicha
propiedad es derivable para todos los términos de un cierto universo siempre que se
pueda demostrar que
1
Es un preorden bien fundado.
3.3. TÉCNICAS PARA LA CONSTRUCCIÓN DE ESPECIFICACIONES
3-47
1. la propiedad es derivable para los términos en cuya expresión no aparece ningún
subtérmino del mismo universo, y
2. la propiedad es derivable para los términos en cuya expresión aparecen subtérminos
del mismo universo cuando se admite como hipótesis (hipótesis de inducción) que
la propiedad se cumple para todos estos subtérminos.
Ejemplo 3.2 Con las restricciones adoptadas, la especificación del álgebra de valores
lógicos se podrı́a reducir a
Universos
Booleanos .
Funciones
v : -> Booleanos .
f : -> Booleanos .
not_ : Booleanos -> Booleanos .
_and_ : Booleanos Booleanos -> Booleanos .
_or_ : Booleanos Booleanos -> Booleanos .
Axiomas
not v = f . not f = v .
X:Booleanos => X and v = X .
X:Booleanos => X and f = f .
X:Booleanos => X or v = v .
X:Booleanos => X or f = X .
pues los demás axiomas son demostrables con ayuda de las reglas de deducción que
acabamos de enunciar. Por ejemplo, podrı́amos demostrar, aplicando la inducción
estructural, que cualquier término del universo Booleanos es equivalente a t o f y,
además que t 6= f, porque su igualdad no es derivable.
3.3
Técnicas para la construcción de especificaciones
Cuando se trata de especificar un determinado dominio de un álgebra A, lo primero que
se hace es pensar en el correspondiente universo s (o tipo de datos) y determinar las
operaciones o funciones asociadas a los elementos de dicho universo. Estas operaciones
se pueden clasificar, desde un punto de vista puramente sintáctico, en
• constructoras, que son aquellas operaciones que producen valores del universo s;
• de observación/consulta, que son las que se aplican sobre valores del universo s
para producir valores de otros universos (son tı́picas operaciones de consulta las
que producen componentes de estructuras complejas, número de componentes o
las que determinan si una estructura está vacı́a).
3-48
CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN.
Dentro de las funciones constructoras se suele distinguir entre:
• constantes, u operaciones que producen valores del universo s sin actuar sobre
ningún argumento, corresponden a funciones de la forma f : → s;
• constantes relativas, u operaciones que producen valores del universo s actuando
exclusivamente sobre argumentos de universos distintos a s; y
• de modificación/transformación, que son todas las demás constructoras.
3.3.1
Estilo constructivo
Existe un estilo de especificación, conocido como estilo constructivo, que consiste en
seleccionar, para cada universo s, un conjunto mı́nimo de operaciones constructoras con
las cuales se puedan expresar todos los valores distintos del correspondiente dominio As ;
es decir, tal que para cada dominio As del álgebra que se quiere especificar, el universo
de términos sin variables de tipo s cubra todos los valores de As y, además, cada término
corresponda a un valor distinto. Cuando se tiene un conjunto Gs de operaciones con
estas caracterı́sticas se dice que se dispone de una familia libre de generadoras para s,
normalmente en estas familias siempre hay alguna constante o constante relativa que
se puede tomar como punto de partida para generar inductivamente todos los términos
del universo s.
En estos casos las demás operaciones se especifican como si estuviésemos dando
sus definiciones en un lenguaje funcional; con las operaciones generadoras se obtienen
los diferentes patrones o formas distintas de construir los términos del universo s y las
operaciones se especifican dando, mediante ecuaciones, los resultados de su aplicación
sobre los distintos términos según su forma —como en un análisis de casos—, procurando que dichos resultados converjan a algún término del universo del resultado. Se
pueden enunciar definiciones
• directas, dando directamente el resultado de cada aplicación;
• recursivas, dando el resultado de una aplicación en función del resultado de otra
aplicación de la misma función (sobre argumentos estrictamente menores en algún
sentido, para que la definición sea convergente);
• con funciones auxiliares, expresando el resultado de una aplicación con ayuda de
alguna función auxiliar; en esta categorı́a entrarı́an las definiciones de funciones
mútuamente recursivas y las definiciones con funciones inmersoras.
Para aclarar todos estos conceptos veamos el ejemplo siguiente correspondiente a
una especificación del álgebra de los números naturales.
3.3. TÉCNICAS PARA LA CONSTRUCCIÓN DE ESPECIFICACIONES
3-49
Ejemplo 3.3 Para especificar el álgebra de los números naturales lo primero que debemos hacer es plantearnos cómo podemos generar todos los valores del álgebra de forma
única. La forma más simple es partir de la constante 0 y aplicar una operación que
produzca los sucesores de cada número, con lo que llegamos a una especificación de la
forma
Universos
Nat .
Generadoras
0 : -> Nat .
s : Nat -> Nat .
Con esto serı́a suficiente para tener todos los valores distintos que se generarı́an inductivamente en la forma
0, s(0), s(s(0)), s(s(s(0))), s(s(s(s(0)))), s(s(s(s(s(0))))), ...
Sin embargo, el álgebra de los números naturales dispone de unas operaciones caracterı́sticas: la suma y el producto, y de una relación de orden total. Cada una de estas
operaciones se puede introducir en la especificación declarando su dominio y recorrido
y definiendo los resultados de sus aplicaciones
Operaciones
_+_ : Nat
_*_ : Nat
Axiomas
N : Nat
N M : Nat
N : Nat
N M : Nat
Nat -> Nat .
Nat -> Nat .
=>
0 + N
=> s(M) + N
=>
0 * N
=> s(M) * N
=
=
=
=
N .
-- def. directa
s(M + N) .
-- def. recursiva
0 .
(M * N) + N .
Para introducir la relación de orden necesitamos incorporar a la especificación el universo Booleanos —junto con sus operaciones generadoras v y f— que figurará como
recorrido de esta relación —en realidad, es una función con valores booleanos—, y
quedará especificada por las ecuaciones
N : Nat =>
0 =< N = v .
N : Nat => s(N) =< 0 = f .
N M : Nat => s(M) =< s(N) = M =< N .
correspondientes a dos definiciones directas y una recursiva. En todos los casos vistos
hasta ahora de definiciones recursivas la aparición, en el lado derecho de la ecuación,
de la operación que se está especificando está siempre aplicada a subtérminos de los
3-50
CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN.
argumentos de partida (lado izquierdo) con uno, al menos, estricto; lo que asegura
la convergencia de dichas definiciones si suponemos que los resultados de todas las
operaciones se pueden reducir siempre a términos construidos sólo con operaciones
generadoras.
Ejercicio 3.1 Especifı́quense las relaciones <, >=, > para el álgebra de los números
naturales.
En estas especificaciones pueden aparecer operaciones parciales, es decir, operaciones que sólo estén definidas para unos ciertos valores de sus dominios, sin necesidad de
introducir predicados nuevos para indicar cuándo están definidos los términos construidos con dichas operaciones (como ocurre en las especificaciones de álgebras parciales)
ni tampoco es necesario un tratamiento de errores. En nuestro caso, la situación se
resuelve introduciendo nuevos universos para ajustar el dominio real de la operación
o para abarcar los resultados indefinidos como si fuesen valores especiales (erróneos).
Cuando se opta por la primera alternativa,
1. se introduce un subuniverso del dominio de la operación y
2. se buscan generadores para este subuniverso;
mientras que cuando se opta por la segunda,
1. se introduce un superuniverso del recorrido,
2. no es necesario buscarle generadores sino que basta con declarar los resultados
de la operación parcial como pertenecientes al superuniverso, y
3. se indica, mediante un axioma condicionado de pertenencia, cuándo se producen
valores correctos;
en ambos casos hay que añadir un axioma condicionado de pertenencia para indicar la
correspondiente relación de contenido entre universos. Veamos cómo se aplican estas
ideas en el caso de los números naturales.
Ejemplo 3.4 Para incorporar a la especificación del álgebra de los números naturales
las operaciones para el cálculo de la diferencia —que sólo está definida cuando el minuendo es mayor o igual que el sustraendo— o del cociente de dos números —que no
está definido cuando el divisor es 0—, debemos introducir nuevos universos de manera
que cada operación quede definida en todo su dominio. En el caso del cociente basta
con no considerar 0 como divisor introduciendo el subuniverso de los naturales no nulos
NatNz, que se generan con la operación s, y declararlos como un universo dentro de
los naturales mediante las declaraciones
3.3. TÉCNICAS PARA LA CONSTRUCCIÓN DE ESPECIFICACIONES
3-51
s : Nat -> NatNz .
P : NatNz => P : Nat .
con lo que la división quedará como una operación total
_div_ : Nat NatNz -> Nat .
En cambio, para la diferencia el problema no se resuelve eliminando un valor del dominio, pues todos pueden intervenir como sustraendo en una resta siempre que el minuendo sea mayor o igual; en este caso, la solución pasa por introducir un universo
más amplio Nat? que contenga los números naturales y todas las posibles expresiones
no calculables —expresiones erróneas— que se generen con la diferencia e indicar, para
esta operación, cuándo produce valores del universo Nat, lo que se hace declarando
_-_ : Nat Nat -> Nat? .
N : Nat => N: Nat? .
M N : Nat, N =< M = v => M - N : Nat .
Las ecuaciones de definición serán
N : Nat => N - 0 = N
M N : Nat => s(M) - s(N) = M - N .
Obsérvese que estas ecuaciones no contemplan todos los posibles casos que se pueden
presentar al restar dos números naturales, ello se debe precisamente a que los casos no
contemplados se consideran erróneos y no se reducen a otras expresiones.
Para el cociente las ecuaciones serán
M : Nat, N : NatNz, N =< M = f => M div N = 0 .
M : Nat, N : NatNz, N =< M = v => M div N = s((M - N) div N) .
donde observamos que los dos casos que se contemplan no dependen de la estructura de
ninguno de los argumentos —como ocurre en las ecuaciones de la diferencia— sino del
resultado de aplicarles una función booleana, que es otra forma de plantear un análisis
de casos. En este caso la convergencia de la definición recursiva queda asegurada
porque la operación div aparece en la parte derecha aplicada a un término M - N que
será estrictamente menor que M respecto a la ordenación dada por =<.
Respecto a las operaciones auxiliares, algunas veces se utilizan simplemente para
facilitar la especificación de otras operaciones y otras porque son prácticamente imprescindibles. En este último caso se encuentran ciertas operaciones auxiliares, conocidas
como operaciones inmersoras, que son más generales (con más parámetros) y más simples que las que se quiere especificar, y tales que, bajo ciertas condiciones, realizan el
mismo cálculo. Existen algunas técnicas, conocidas como técnicas de inmersión, para
3-52
CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN.
determinar operaciones de este tipo para una operación f dada cuando se conoce su
especificación pre/post. Veamos algunas.
Inmersión por debilitamiento de la postcondición. Esta técnica se basa en
buscar una operación que realice un cálculo más simple que f hasta el punto que, en
algún caso extremo, el cálculo sea directo, mientras que, en los demás casos, se puedan
utilizar los resultados de aplicaciones recursivas más simples para facilitar el cálculo de
la aplicación original.
Se procede debilitando la postcondición de f , normalmente parametrizando alguna
subexpresión que se pueda utilizar para controlar el grado de aproximación al cálculo
buscado ası́ como la simplicidad del cálculo necesario, este parámetro pasa como argumento a la función auxiliar, cuya precondición será la de f reforzada con las condiciones
que deba cumplir el nuevo parámetro. Veamos un ejemplo.
Ejemplo 3.5 Consideremos la tarea de especificar una operación para obtener raı́ces
cuadradas. Esta operación, raiz (N ), se caracteriza porque debe calcular, para cada
número N , un valor R tal que (R ∗ R ≤ N ) ∧ (N < (R + 1) ∗ (R + 1)) (postcondición
de la función). Dicha operación no admite una definición recursiva, pero considerando
la postcondición en la forma (R ∗ R ≤ N ) ∧ (N < (R + A) ∗ (R + A)) ∧ (A = 1),
donde se ha introducido un parámetro A que representa el margen de error de la raı́z
cuadrada, podemos pensar en una operación inmersora recursiva que realice un cálculo
más general: rz (N, A) con postcondición (R∗R ≤ N ) ∧ (N < (R+A)∗(R+A)) ∧ (A ≥
1), es decir, que calcule una aproximación de la raı́z cuadrada con margen de error
A ≥ 1. Esta operación
rz : Nat NatNz -> Nat .
es más simple de especificar porque, para márgenes de error suficientemente grandes,
0 es un resultado válido,
N:Nat, A:NatNz, A*A =< N = f => rz(N,A) = 0 .
y se puede obtener una aproximación para un cierto margen A ≥ 1 a partir de otra con
un margen A + A de una manera simple;
N:Nat, A:NatNz, (rz(N,A+A)+A)*(rz(N,A+A)+A) =< N = v
=> rz(N,A) = rz(N,A+A)+A .
N:Nat, A:NatNz, A*A =< N = v, (rz(N,A+A)+A)*(rz(N,A+A)+A) =< N = f
=> rz(N,A) = rz(N,A+A) .
además calculará la raı́z cuadrada cuando el margen de error sea A = 1, es decir, que
tendremos raiz(N) = rz(N,s(0)).
3.3. TÉCNICAS PARA LA CONSTRUCCIÓN DE ESPECIFICACIONES
3-53
Inmersión por refuerzo de la precondición. Esta técnica se basa en buscar una
operación que realice el mismo cálculo que la operación original, pero disponiendo de
información adicional que le llegue mediante parámetros auxiliares de manera que, en
un caso extremo, la información proporcionada por estos parámetros sea suficiente para
obtener el resultado mediante un cálculo directo, mientras que, en los demás casos, se
pueda mejorar la información de los parámetros auxiliares y pasarla a alguna aplicación
recursiva que realice el cálculo final disponiendo de una mejor información.
Se procede aumentando el número de parámetros de f con algún parámetro que
represente un cálculo parcial o una aproximación del resultado. Este parámetro se suele
obtener a partir de alguna subexpresión de la postcondición relacionada con el resultado
que pueda servir como acumulador o como aproximación o cota —en algunos casos se
utiliza el mismo resultado como parámetro— y la postcondición se descompone en una
conjunción de dos fórmulas, una de las cuales se utiliza para reforzar la precondición de
f , que se utiliza para indicar cuándo se producen resultados correctos, y la otra para
controlar el caso base. Veamos un ejemplo también con la raı́z cuadrada.
Ejemplo 3.6 Podemos parametrizar el resultado en la postcondición de la raı́z cuadrada, que quedarı́a (A ∗ A ≤ N ) ∧ (N < (A + 1) ∗ (A + 1)) —donde el nuevo parámetro
A representa una aproximación por defecto de la raı́z—, y podemos tomar A ∗ A ≤ N
como precondición para una función auxiliar
rz’ : Nat Nat -> Nat? .
que no estará definida para todos los valores de sus argumentos —como indica la aparición de Nat? en el recorrido—, y N < (A + 1) ∗ (A + 1) para controlar el caso trivial
en la definición de esta función
A*A =< N = v, s(A)*s(A) =< N = f => rz’(N,A) = A .
para el caso general, la aproximación por defecto puede mejorarse simplemente utilizando el número siguiente
s(A)*s(A) =< N = v => rz’(N,A) = rz’(N,s(A)) .
La raı́z cuadrada quedarı́a raiz(N) = rz’(N,0).
Para descargar un poco la sintaxis vamos a introducir las siguientes simplificaciones
dentro de una especificación:
1. Ordenación de universos. Los axiomas de la forma X:T => X:T’, que se utilizan
para declarar que el universo T está contenido en el universo T’, se pueden omitir
escribiendo en su lugar T < T’ en la declaración de universos.
3-54
CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN.
2. Declaración de variables. Las declaraciones de tipo para las variables que aparecen en cada ecuación se pueden suprimir de las condiciones de las ecuaciones
escribiendo una sola declaración de tipo separada para las variables de cada tipo
T que aparezcan en la especificación, en la forma VAR X ... Z:T.
3. Funciones con el mismo perfil. Las declaraciones de funciones f, g, que tengan el
mismo dominio y el mismo recorrido (el mismo perfil) se pueden agrupar en una
sola declaración de la forma f g : T1 ... Tk -> T.
4. Ecuaciones con términos booleanos. Las ecuaciones de la forma e = v y e = f,
siendo e una expresión booleana, que aparezcan en las condiciones de un axioma
se pueden escribir como e o not e respectivamente.
5. Construcción alternativa. Cuando en una especificación aparecen axiomas ecuacionales, referidos al mismo término t, de la forma
C, c = v => t = a .
C, c = f => t = b .
donde C representa un conjunto —posiblemente vacı́o— de condiciones, se puede
escribir una sola ecuación de la forma
C => t = SI c ENTONCES a SI NO b FIN .
Ejemplo 3.7 Aplicando simplificaciones anteriores a la especificación del álgebra de
los números naturales con las operaciones que hemos visto en los distintos ejemplos
anteriores tendrı́amos la especificación siguiente
Universos
NatNz < Nat < Nat? .
Booleanos .
Generadoras
0 : -> Nat .
s : Nat -> NatNz .
v f : -> Booleanos .
Operaciones
_+_ _*_ : Nat Nat -> Nat .
_-_ : Nat Nat -> Nat? .
_div_ : Nat NatNz -> Nat .
_=<_ : Nat Nat -> Booleanos .
Axiomas
VAR M N :Nat . VAR P :NatNz .
3.3. TÉCNICAS PARA LA CONSTRUCCIÓN DE ESPECIFICACIONES
3-55
0 + N = N .
s(M) + N = s(M + N) .
0 * N = 0 .
s(M) * N = (M * N) + N .
0 =< N = v .
s(N) =< 0 = f .
s(M) =< s(N) = M =< N .
N =< M => M - N : Nat .
N - 0 = N
s(M) - s(N) = M - N .
M div P = SI P =< M ENTONCES (M - P) div P
SI NO 0 FIN .
Ejercicio 3.2 Especifı́quense en el álgebra de los números naturales las operaciones
_mod_ : Nat NatNz -> Nat .
par? : Nat -> Booleanos .
la primera de las cuales calcula el resto de la división de dos números y la segunda
determina si un número es par.
Las ventajas más notables del estilo constructivo de especificación residen en que
1. Las ecuaciones se construyen para que el resultado de la aplicación de cada operación (salvo en operaciones parciales que pueden producir resultados erróneos)
se pueda reducir a un término construido sólo con operaciones generadoras, que
será la forma irreducible o el “valor” del término.
2. Se puede controlar la consistencia y la completitud de las especificaciones de
una forma meramente sintáctica, pues basta con definir cada operación mediante
ecuaciones aplicables a términos que obedezcan a patrones o casos distintos y
considerar todos los patrones o casos que se puedan dar.
3. Se simplifica el razonamiento por inducción estructural pues, como los términos
de cada universo se pueden reducir a términos construidos únicamente con las
operaciones generadoras, sólo hay que tener en cuenta estas formas al aplicar
dicho razonamiento.
4. Se puede realizar la ejecución simbólica de las especificaciones, para reducir
términos, considerando las ecuaciones como reglas de reescritura de izquierda
a derecha.
Veamos cómo se aplica el razonamiento por inducción con un ejemplo sobre el
álgebra de los números naturales.
3-56
CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN.
Ejemplo 3.8 En el álgebra especificada en el Ejemplo 3.7 se cumple la propiedad conmutativa para la suma. Para demostrarla, procederemos probando primero que se cumplen las propiedades ∀N : Nat · (N + 0 = N ) y ∀M, N : Nat · (M + s(N ) = s(M + N )).
La primera propiedad se demuestra por inducción sobre la estructura de N ; ası́ para
N = 0, transformando sucesivamente la ecuación (preferentemente la parte izquierda),
tenemos
N + 0 =? N, por la hipótesis N = 0 queda
0 + 0 =? 0, por el axioma 0 + N = N queda
0 = 0, cierto por la reflexividad de =,
y para N = s(X), admitiendo como hipótesis de inducción X + 0 = X, tenemos
N +0
s(X) + 0
s(X + 0)
s(X)
=?
=?
=?
=
N,
s(X),
s(X),
s(X),
por la
por el
por la
cierto
hipótesis N = s(X) queda
axioma s(M ) + N = s(M + N ) queda
hipótesis de inducción resulta
por la reflexividad de =.
Para demostrar la segunda propiedad procederemos por inducción sobre la estructura
del término M ; ası́ para M = 0 tenemos
M + s(N )
0 + s(N )
0 + s(N )
s(N )
=?
=?
=?
=
s(M + N ),
s(0 + N ),
s(N ),
s(N ),
por la
por el
por el
cierto
hipótesis M = 0 queda
axioma 0 + N = N queda
axioma 0 + N = N queda
por la reflexividad de =,
y para M = s(X), admitiendo como hipótesis de inducción X + s(N ) = s(X + N ),
tenemos
M + s(N )
s(X) + s(N )
s(X) + s(N )
s(X + s(N ))
s(s(X + N ))
=?
=?
=?
=?
=
s(M + N ),
s(s(X) + N ),
s(s(X + N )),
s(s(X + N )),
s(s(X + N )),
por la
por el
por el
por la
cierto
hipótesis M = s(X) queda
axioma s(M ) + N = s(M + N ) queda
axioma s(M ) + N = s(M + N ) queda
hipótesis de inducción resulta
por la reflexividad de =.
Ahora ya se puede abordar la demostración de la propiedad conmutativa ∀M, N : N at ·
M + N = N + M , para ello se puede proceder por inducción sobre la estructura de M y
utilizar las propiedades demostradas anteriormente. Dejamos esta demostración como
ejercicio.
3.3.2
Estilo semiconstructivo
Algunas veces no es posible encontrar una familia libre de operaciones generadoras para
un álgebra, sino que, a lo más, se llega a obtener una familia de operaciones que generan
términos distintos para un mismo valor del álgebra. En estos casos hay que introducir
3.3. TÉCNICAS PARA LA CONSTRUCCIÓN DE ESPECIFICACIONES
3-57
ecuaciones para establecer las identificaciones necesarias entre términos producidos
por las operaciones generadoras; normalmente —aunque no siempre—, ecuaciones que
permitan reducir los distintos términos construidos con las operaciones generadoras
a formas irreducibles. Ası́, cada valor del álgebra se corresponderá con una clase
de equivalencia de términos respecto a la relación producida por estas ecuaciones y se
toman las formas irreducibles —cuando existen, hay una única para todos los elementos
de una misma clase— como representantes, o formas canónicas, de las distintas clases.
Ejemplo 3.9 Consideremos el álgebra de los números enteros. Los valores de este
álgebra se pueden generar a partir de la constante 0 mediante aplicaciones sucesivas
de las operaciones sucesor, s:Ent -> Ent, y predecesor, p:Ent -> Ent, que generan
respectivamente, el número siguiente y el número anterior de un número dado; sin
embargo, hay términos distintos generados con estas operaciones que deben representar
un mismo número, por ejemplo, s(0) y s(p(s(0))) deben representar en número 1.
En general tendremos infinitos términos distintos para cada número, lo que nos obliga
a introducir en la especificación las ecuaciones
s(p(N)) = N .
p(s(N)) = N .
que permiten identificar representaciones equivalentes, indicando ası́ que la familia de
generadoras no es libre y que los distintos valores del universo Ent serán las clases
de equivalencia de términos correspondientes a la relación definida por las ecuaciones
anteriores; ası́, por ejemplo, el número 1 vendrá dado por la clase de equivalencia
correspondiente a los términos
s(0), s(p(s(0))), p(s(s(0))), s(s(p(0))), ...
todos los cuales se pueden reducir a la forma irreducible s(0) aplicando las ecuaciones
anteriores.
En estos casos, aun es posible aplicar las técnicas de las especificaciones constructivas, aunque hay que tener mucho más cuidado con la consistencia de las ecuaciones
pues las operaciones realmente deberı́an actuar sobre clases de equivalencia y producir
como resultado clases de equivalencia, pero las definiciones de dichas operaciones hay
que hacerlas sobre términos generados con las operaciones generadoras, produciendo
términos. Por ello las definiciones deben hacerse de forma que cuando una operación se aplique a términos equivalentes los resultados que se obtengan también sean
equivalentes. Veamos un ejemplo con los números enteros.
Ejemplo 3.10 En el álgebra de los números enteros, las distintas operaciones aritméticas _+_, _-_ y _*_ se pueden definir en la forma
3-58
CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN.
_+_ _-_ _*_ : Ent Ent -> Ent .
VAR Z Z’ : Ent .
0 + Z = Z .
s(Z’) + Z = s(Z’ + Z) .
-- saca las generadoras s y p fuera
p(Z’) + Z = p(Z’ + Z) .
-- del primer argumento
Z - 0 = Z .
Z - s(Z’) = p(Z - Z’) .
-- saca las generadoras s y p fuera
Z - p(Z’) = s(Z - Z’) .
-- del segundo argumento intercambiadas
0 * Z = 0 .
s(Z’) * Z = (Z’ * Z) + Z . -- reduce productos a sumas o restas
p(Z’) * Z = (Z’ * Z) - Z .
donde las definiciones tienden a reducir los términos construidos con las operaciones a
términos sólo con operaciones generadoras y los resultados de las operaciones se mantienen equivalentes para argumentos equivalentes. Por ejemplo, s(p(0))+p(s(s(0)))
y s(p(0))+s(0) que son sumas de términos equivalentes se pueden reducir ambas a
s(0).
En esta especificación podemos incluir los números naturales declarándolos como
un universo dentro de los enteros
NatNz < Nat < Ent .
0 : -> Nat .
N : Nat => s(N) : NatNz .
y utilizarlos para definir una relación de orden en la forma
_=<_ : Ent Ent
VAR Z Z’ : Ent
Z’ - Z : Nat
Z - Z’ : NatNz
-> Booleanos .
.
=> Z =< Z’ = v .
=> Z =< Z’ = f .
Con las especificaciones semiconstructivas también se puede limitar el razonamientos por inducción estructural a términos construidos sólo con operaciones generadoras.
Ejercicio 3.3 Demuéstrese, aplicando inducción estructural,
1. que la suma definida en Ent tiene la propiedad conmutativa;
2. para Z : Ent se cumple Z = 0 o Z = sn (0) con n > 0, o Z = pn (0) con n > 0;
3. para Z : Ent existe Z 0 : Ent tal que Z = Z 0 + Z 0 o Z = s(Z 0 + Z 0 ).
Ejercicio 3.4 Especifı́quese un universo Dia correspondiente a los dı́as de la semana
considerando que se generan a partir del lunes (Lu) aplicando la operación ds:Dia->Dia
que produce el dı́a siguiente de cada dı́a. Inclúyase también una operación da:Dia->Dia
que produzca el dı́a anterior.
3.4. PATRONES PARA LA ESPECIFICACIÓN DE TIPOS ABSTRACTOS
3.4
3-59
Patrones para la especificación de tipos abstractos
Existen unos patrones o formas generales para la especificación de universos, ya sea
directamente o a partir de otros universos ya definidos —muchos de los cuales están
recogidos en los modernos lenguajes de programación fuertemente tipificados bajo la
forma de esquemas para la definición de tipos— que suelen aplicarse a la hora de
plantearse la especificación de un tipo abstracto nuevo correspondiente a un álgebra.
Veamos los más comunes.
3.4.1
Enumeración
Es el patrón más simple y se utiliza para especificar álgebras con un número muy
reducido de valores, por ejemplo, v1 , · · · , vk . En este caso, lo que se hace es especificar
el correspondiente universo junto con una constante por cada valor
Universos
T .
Generadoras
v1 : -> T .
...
vk : -> T .
Un ejemplo tı́pico lo constituye la especificación del álgebra de valores lógicos. Este
patrón se puede identificar con el esquema de definición de tipos por enumeración que
aparece en algunos lenguajes imperativos de programación.
Ejercicio 3.5 Enúnciese una especificación correspondiente al álgebra de las notas
musicales.
Ejercicio 3.6 Enúnciese la especificación correspondiente al álgebra de los dı́as de la
semana considerándolos como valores constantes y especifı́quense, para este caso, las
operaciones ds y da.
3.4.2
Suma directa
Este patrón T = T1 | · · · |Tn se aplica a la especificación de álgebras A que se pueden considerar como la unión disjunta de otras álgebras A1 , ...,An ; es decir, tales que
sus elementos son los elementos diferenciados de todas y cada una de estas álgebras.
Consiste en introducir un universo global T junto con los universos T1,...,Tn, correspondientes a las álgebras componentes, y declararlos subuniversos de T, manteniendo las
operaciones generadoras de cada uno de ellos y no incluyendo ninguna operación que
genere directamente valores del universo T—. Con el uso de fórmulas de pertenencia
3-60
CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN.
se puede saber la procedencia de cualquier término del universo T. La especificación
quedarı́a en la forma
Universos
T1 < T .
...
Tn < T .
Generadoras
-- las de cada universo T1, ..., Tn
Este patrón se suele utilizar para agregar valores especiales a un universo dado, por
ejemplo, valores de error para desarrollar un tratamiento de errores, o simplemente
para añadir más valores al dominio de una operación. El patrón de enumeración se
puede considerar un caso particular de suma directa de universos reducidos a un único
valor.
3.4.3
Producto cartesiano
Este patrón T = T1 × · · · × Tn se utiliza para especificar álgebras A que se pueden considerar como el producto cartesiano de otras álgebras A1 , ...,An ; es decir, tales que sus
elementos son tuplas de n componentes, cada componente de una de las álgebras anteriores. Cuando se aplica este patrón se introduce el universo T junto con los universos
T1,...,Tn, correspondientes a las álgebras componentes, y sus respectivas operaciones generadoras. Los valores del universo T se generan mediante una única constante relativa
que construye las tuplas a partir de sus componentes, y se añaden operaciones (proyecciones) para consultar las distintas componentes de cada valor. El aspecto general
de una especificación por producto cartesiano es el siguiente
Universos
T1 .
...
Tn .
T .
Generadoras
(_,...,_) : T1 ... Tn -> T .
-- todas las de T1, ..., Tn
Operaciones
pr1 : T -> T1 .
...
prn : T -> Tn .
Axiomas
VAR t1:T1 .
3.4. PATRONES PARA LA ESPECIFICACIÓN DE TIPOS ABSTRACTOS
3-61
...
VAR tn:Tn .
pr1 (t1,...,tn) = t1 .
...
prn (t1,...,tn) = tn .
Este patrón coincide con el esquema para la definición de registros de los lenguajes
imperativos de programación, en los que los nombres de los distintos campos hacen el
papel de las proyecciones pr, y cuando se combina con la suma directa, se obtienen
patrones mixtos como T = (T1 |T2 ) × T2 × · · · × Tn equivalente a un esquema para la
definición de registros con variantes.
Ejercicio 3.7 Especifı́quese el álgebra de vectores del plano con coordenadas enteras
con sus operaciones tı́picas (limitadas a números enteros) y con operaciones
_||_ : Vect2 Vect2 -> Booleanos .
_-|_ : Vect2 Vect2 -> Booleanos .
para determinar si dos vectores son paralelos o si son perpendiculares.
Ejercicio 3.8 Amplı́ese la especificación anterior con un universo para los puntos del
plano con coordenadas enteras y con operaciones
vector : Punto Punto -> Vector .
trasl : Punto Vect2 -> Punto .
scentral : Punto Punto -> Punto .
para producir el vector determinado por dos puntos, el punto producido al aplicar un
vector a un punto y el punto simétrico de otro respecto a un centro de simetrı́a dado
por el segundo argumento.
Ejercicio 3.9 Enúnciese una especificación para el álgebra de los números racionales,
basada en los números enteros y los naturales no nulos, con las cuatro operaciones
aritméticas.
3.4.4
Cociente
Este patrón T = T 0 / ∼
= se utiliza para especificar álgebras A que se pueden considerar
como el cociente de otras álgebras A0 respecto a una relación de equivalencia ∼
= definida
entre sus elementos; es decir, tales que sus elementos se pueden considerar clases de
equivalencia de elementos de las álgebras A0 . Para dar una especificación siguiendo este
patrón, se introducen los géneros T y T’ junto con las operaciones generadoras de T’ y
se establece la relación de equivalencia entre los términos de T’ como ecuaciones en el
apartado de axiomas. Este patrón es propio de las especificaciones semiconstructivas,
aunque en dichas especificaciones se omite la mención explı́cita del universo T 0 .
3-62
CAPÍTULO 3. MÉTODO ALGEBRAICO DE ESPECIFICACIÓN.
Ejercicio 3.10 Enúnciese una especificación para el álgebra de los números racionales a partir del producto cartesiano Ent × NatNz con sus operaciones aritméticas y
relaciones de orden tı́picas.
Ejercicio 3.11 Amplı́ese la especificación del Ejercicio 3.8 añadiendo un universo para las rectas dadas como pares (punto,vector), estableciendo con cuidado las ecuaciones
entre las distintas representaciones equivalentes de una misma recta, y definiendo la
relación de pertenencia entre puntos y rectas.
3.4.5
Recursión
El uso de la recursión da lugar a una infinidad de patrones caracterı́sticos de aquellas
álgebras cuyos valores se obtienen mediante constructoras aplicadas a valores de la
misma álgebra. Los patrones recursivos aparecen cuando un universo se define como
suma directa de otros universos en cuyas definiciones aparece el propio universo; en
estos casos es necesario que en alguno de los sumandos de la suma directa no aparezca el
universo que se define para que la recursión tenga sentido. Tienen patrones recursivos
Nat, que se puede considerar que obedece al patrón Cero | s(Nat), las listas de números
naturales ListaNat que obedecen al patrón Nil | (Nat × Lista) y los árboles binarios con
números naturales en las hojas ArbolHNat que obedecen al patrón N at | (ArbolHNat ×
ArbolHNat).
Combinando patrones recursivos con cocientes se obtienen especificaciones para conjuntos, bolsas, aplicaciones y grafos. También se pueden construir patrones utilizando
recursión mútua como ocurre con el siguiente patrón, que se utiliza para la especificación de árboles generales de números naturales ArbolGNat, donde estos árboles se definen conjuntamente con listas de árboles o BosqueNat siguiendo los esquemas siguientes
ArbolGNat = N at × BosqueNat y BosqueNat = Nil | (ArbolGNat × BosqueNat).
Ejercicio 3.12 Enunciad especificaciones para bolsas y conjuntos de números naturales limitando la especificación a las operaciones generadoras y sus ecuaciones.
Ejercicio 3.13 Enunciad especificaciones para relaciones binarias con números naturales, para relaciones simétricas y para aplicaciones.
3.5. ORGANIZACIÓN MODULAR DE LAS ESPECIFICACIONES
3.5
3-63
Organización modular de las especificaciones
A la hora de especificar álgebras complejas con varios dominios se puede llegar a tener
especificaciones demasiado extensas difı́ciles de controlar; en estos casos conviene proceder por partes, construyendo primero especificaciones simples, posiblemente correspondientes a dominios individuales, y, sobre ellas, otras especificaciones más complejas
hasta llegar a la especificación pretendida. Esta labor se facilita enormemente disponiendo de algún mecanismo sintáctico para individualizar partes de una especificación
y para incorporar o integrar unas partes en otras sin tener que volver a escribirlas. Para
esto aparecen los lenguajes modulares de especificación que permiten localizar especificaciones en módulos y permiten también que distintos módulos se puedan integrar
dentro otros mediante algún mecanismo de importación. De esta forma, definiendo
módulos correspondientes a universos individualizables dentro de una especificación
y estableciendo relaciones de importación de unos módulos sobre otros se consigue
estructurar especificaciones muy extensas en piezas (módulos) pequeñas, fácilmente
manejables. Las especificaciones obtenidas mediante un mecanismo de este tipo —
siempre que no se establezcan dependencias circulares entre módulos— se denominan
especificaciones jerarquizadas.
La idea de los patrones de especificación que hemos visto de una manera informal
en la sección 3.4 se puede formalizar de una manera más detallada y sobre la base de
un lenguaje modular de especificación. La idea surge de que, a veces, determinadas
especificaciones jerarquizadas —especialmente las correspondientes a tipos de datos
estructurados— tienen una apariencia común diferenciándose sólo en algún universo
o grupo de operaciones importado. Para manejar estos casos de una forma unificada
resulta conveniente que el lenguaje de especificación permita la definición de “funciones” entre especificaciones o, como se suelen denominar generalmente, especificaciones
genéricas parametrizadas en otras especificaciones, tales que, a partir de una de ellas se
puedan conseguir distintas especificaciones con una misma estructura simplemente instanciando, mediante algún mecanismo de instanciación, las especificaciones parámetro
que, en el caso de los lenguajes modulares vienen dadas por módulos.
En adelante nos ocuparemos del estudio de uno de estos lenguajes modulares de
especificación. Se trata del lenguaje MAUDE desarrollado en el SRI International por
un equipo de investigadores encabezado por J. Meseguer.
Descargar