Especificación - Universidad de La Rioja

Anuncio
Presentaciones de teoría de la
asignatura “Especificación y
Desarrollo de Sistemas de
Software”
Grado en Matemáticas y Grado en
Ingeniería Informática
Ana Romero Ibáñez
Universidad de La Rioja
Curso 2011/2012
Todo este material está disponible en la página web:
www.unirioja.es/cu/anromero/edss.html
Índice
Tema 1 - Abstracción y formalismo en Programación……………… 3
Tema 2 - Especificación/Implementación de tipos de datos……….21
Tema 3 - Tipos abstractos y orientación a objetos………………….57
Tema 4 - Especificación de algoritmos……………………………….77
Tema 5 - Sintaxis y semántica de un lenguaje
imperativo sencillo…………………………………………100
Tema 6 - Nociones sobre eficiencia. Verificación
formal de la corrección de algoritmos……………………132
Tema 1: Introducción.
Abstracción y formalismo en
Programación
Especificación y Desarrollo de Sistemas de Software
Universidad de La Rioja
Ana Romero Ibáñez
Programa de la asignatura






Introducción: "Abstracción y formalismo en
Programación".
Especificación/Implementación de tipos de datos.
Tipos abstractos y orientación a objetos.
Especificación de algoritmos.
Sintaxis y semántica de un lenguaje imperativo
sencillo.
Nociones sobre eficiencia. Verificación formal de la
corrección de algoritmos.
Métodos formales y abstracción en Programación
2
Proceso de abstracción


Destacar algunos aspectos relevantes del
objeto de estudio
Ignorar detalles no relevantes
Objetivo: obtener una visión más simple y
formal del objeto de estudio (generalmente
proporciona un conocimiento más profundo
del mismo).
3
Proceso de abstracción
4
Abstracción en Programación



Programación: tarea compleja y altamente
proclive a errores, difícil de depurar, costoso
de modificar.
A partir de la crisis del software (60’s, 70’s),
se empiezan a introducir algunas técnicas y
métodos de corte formal (por ejemplo
formalismos matemáticos).
Uso de métodos formales para definir
objetos (datos) y procesos (acciones).
5
Abstracción a nivel de acciones






Lenguajes de alto nivel frente a
lenguaje máquina o ensamblador.
Subalgoritmos.
Especificación, cabeceras, interfaces.
Programación funcional y
programación lógica.
Derivación automática de código.
Esquemas algorítmicos, patrones.
6
Abstracción a nivel de datos





Tipos predefinidos.
Constructores de estructuras.
Especificación de tipos, tipo abstracto.
Mecanismos de ocultación de
información y de encapsulamiento.
Clases, parametrización, polimorfismo.
7
Abstracción en Programación
8
Abstracción en Programación
“La historia de la Programación es un camino hacia
un grado creciente de abstracción, que se usa
como un mecanismo para disminuir la
complejidad”.
9
Abstracción a nivel de datos
Es deseable poder manejar los tipos
definidos por el programador igual que
los predefinidos:
 Definir y crear variables del tipo
 Manipular los datos con las
operaciones definidas
 Conocer su comportamiento
10
Primera aproximación a la noción de
Tipo Abstracto de Datos
Un Tipo Abstracto de Datos (TAD) consta
de uno o varios conjuntos (dominios del
tipo) y un conjunto de funciones entre
dichos conjuntos (operaciones del tipo)
definidos mediante una especificación sin
hacer referencia a ningún detalle de
implementación.
11
Primera aproximación a la noción de
Tipo Abstracto de Datos
Para implementar un tipo de datos habrá
que dar:
 Una representación de los datos de
los dominios.
 Programas que implementen las
operaciones.
12
Especificación frente a
implementación

Especificación: ¿QUÉ?

Implementación: ¿CÓMO?
EXTERIOR
(abstracto)
Dominio
INTERIOR
(concreto)
Representación
de los datos
(instancias del
tipo)
+
Datos
Programas que
implementan las
operaciones
13
Especificación frente a
implementación


El usuario sólo debe conocer la “capa
externa” (especificación).
El programador debe preocuparse de las
dos capas:


Tener bien especificado el tipo y bien descrito
su comportamiento.
Buscar representaciones adecuadas para los
dominios y desarrollar programas que
implementen las operaciones.
14
Especificación frente a
implementación

El programador tiene que tener muy
clara la función de abstracción: función
que determina qué dato externo está
representado por cada dato interno.
15
Ejemplo: especificación de pilas de
enteros
Especificación PILASENTEROS
- usa BOOL, ENT // especificaciones previas
- géneros pila
- operaciones
pVacia :  pila
apilar : pila ent  pila (parcial)
desapilar : pila  pila (parcial)
cima : pila  ent (parcial)
estaVacia : pila  bool
- propiedades:
desapilar(apilar(p,n)) p
nm  apilar(apilar(p,n),m)  apilar(apilar(p,m),n)
16
Ejemplo: implementación de pilas de
enteros

Una pila de enteros se puede representar
mediante una pareja (registro) <v,n> donde v es un
vector de enteros y n es un entero ( 0
(visto en Tecnología de la Programación).
…
v=
17
n=
4
-3
0
8
…
Función de abstracción
8
0
-3
17
17
Bibliografía

R. Peña. “Diseño de programas: formalismo
y abstracción”. Prentice Hall, 1997.
18
Tema 2: Especificación e
Implementación de
Tipos de Datos
Especificación y Desarrollo de Sistemas de Software
Universidad de La Rioja
Ana Romero Ibáñez
Aproximación a la noción de Tipo
Abstracto de Datos

Un Tipo Abstracto de Datos (TAD) es
una colección de valores y de
operaciones que se definen mediante
una especificación que es
independiente de cualquier
representación.
2
Aproximación a la noción de Tipo
Abstracto de Datos
En realidad este concepto es similar a los tipos
predefinidos.

Ejemplo:

Definición del tipo de datos de los enteros en C++/Java

valores: los del intervalo
[MIN_VALUE,MAX_VALUE]

operaciones: +, -, *, /, resto, …

propiedades de las operaciones: a+b=b+a, ...
No hay que saber nada sobre implementación
3
Aproximación a la noción de Tipo
Abstracto de Datos

La manipulación de un TAD sólo debe
depender de su especificación, nunca
de su implementación.
Para manipular los enteros nos olvidamos de
cómo se representan los valores y de cómo
están implementadas las operaciones.
4
Aproximación a la noción de Tipo
Abstracto de Datos
De este modo conseguiremos:

Privacidad: los usuarios no conocen la
representación de los valores.

Protección: sólo se pueden utilizar las
operaciones definidas en la especificación.
En particular, el conjunto de operaciones ha
de permitir generar cualquier valor del tipo.
5
Aproximación a la noción de Tipo
Abstracto de Datos

Dada una especificación de TAD hay
muchas implementaciones válidas.

Un cambio de implementación de un
TAD es transparente a los programas
que lo utilizan.
6
Aproximación a la noción de Tipo
Abstracto de Datos
El programador debe crear:
 Especificación: dominios +
operaciones + comportamiento.
 Implementación: representación de
los dominios + implementación de las
operaciones en términos de la
representación dada.
7
Aproximación a la noción de Tipo
Abstracto de Datos
Abstracción:
 Se destacan los detalles de la
especificación (el comportamiento
observable del tipo, qué hace).
 Se ocultan los detalles de la
implementación
(cómo lo hace).
8
Especificación de tipos de datos

El documento de especificación de un tipo
de datos debe contener el interfaz del tipo
(nombre y cabecera de los operadores) y
una descripción del comportamiento
(significado) de esos operadores, sin
ninguna referencia a detalles de
implementación.

La idea es que la especificación de un tipo
de datos debe servir para determinar un
“modelo abstracto” externo que
corresponda al comportamiento deseado.
9
Especificación de tipos de datos

Tanto para dar la especificación como para
determinar el modelo usaremos
herramientas del “mundo de las
matemáticas”.
10
Especificación de tipos de datos
Una especificación constará de:
 Nombres de los dominios del tipo.
 Nombres y cabeceras de los
operadores.
 Comportamiento esperado de las dos
partes anteriores.
11
Especificación de tipos de datos
Formalizando lo anterior:
Definición : Una signatura  está formada por dos
conjuntos   S,  . El primero de ellos se denomina
conjunto de géneros de la signatura, y el segundo se
denomina conjunto de operadores. Cada operador
lleva asociado además una secuencia no vacía de
géneros (cabecera del operador).
12
Especificación de tipos de datos
Signatura de pilas  p  S p ,  p 
Sp   a, e, b 
vac :  a; op1 : a e  a 


 p  op2 : a  a; op3 : a  e 

op 4 : a  b


¡OJO! Sólo se trata de símbolos (sintaxis).
Falta dar significado a lo anterior.
13
Especificación de tipos de datos
Definición : dada una signatura   S,  , un álgebra
o modelo Α para  consta de :
- Para cada género g  S, un conjunto A g ( soporte para
el género g).
- Para cada operación w  ,w : g1 ... gk  g, una función
w  : A g1    A gk  A g (interpretación del operador w en Α).

Α  (A g )gS , (w  )w

14
Especificación de tipos de datos
En el ejemplo de la signatura de pilas, un álgebra
puede ser:
a={pilas de enteros}=
e=  (enteros)
b=  (booleanos)
vac=pVacia:  
op1=apilar:  x    ((x1,…xk),n) (x1,…xk,n)
op2=desapilar:    (x1,…xk) con k (x1,…xk-1)
op3=cima:   (x1,…xk) con k  xk
op4=estaVacia:   (x1,…xk)0 si k=0, 1 en otro caso
15
Especificación de tipos de datos
Otro modelo para  p puede ser:
a={colas de enteros}=
e=  (enteros)
b=  (booleanos)
vac=cVacia:  
op1=encolar:  x   
op2=desencolar:   
op3=primero:   
op4=estaVacia:   
16
Especificación de tipos de datos
Más ejemplos:
 Signatura + modelo(s) para las listas con
posición.
 Signatura + modelo(s) para los naturales.
 Signatura + modelo(s) para los booleanos.
 Signatura + modelo(s) para las fichas de
dominó.
17
Especificación de tipos de datos
s
o
t
a
D
e
d
o
t
c
a
r
t
s
b
A
o
p
i
T
Definición : Un
(TAD) está formado por una signatura
  S ,   y una clase (" familia" ) de
modelos de  .
18
Especificación de tipos de datos
Problemas:
 Pocas veces podemos dar una
descripción precisa de un modelo.
 Lo habitual es utilizar algún tipo de
técnica de definición en matemáticas
para dar la clase de modelos. La más
usada es la especificación
algebraica (ecuacional).
19
Especificación de tipos de datos
Definición : Una Especificación Algebraica
es una pareja E  ( , Ec ) donde  es una
signatura y Ec es un conjunto de " ecuaciones"
sobre los géneros y operaciones de  .
20
Especificación de tipos de datos
Distintas formas de dar significado a una
especificación:
 Todos los modelos de la signatura que
satisfacen las ecuaciones.
 Modelo inicial:


Generado por las operaciones (sin basura).
Las únicas propiedades que se cumplen son
las ecuaciones y los teoremas que se deducen
de ellas.
21
Especificación de tipos de datos
Nuestra forma de especificar será semiformal:
 Seremos rígidos al escribir las signaturas.
 Para el comportamiento nos basaremos en
modelos conocidos, de la forma más
precisa posible.
 Nuestras especificaciones no serán válidas
para probar la corrección de programas que
utilicen el TAD.
22
Especificación de tipos de datos
Ejemplo: conjuntos finitos de enteros
Especificación CONJENTEROS
usa ENTERO, BOOL
géneros conj
operaciones
vacío :  conj
estáVacio : conj  bool
pertenece : conj ent  bool
unión : conj conj  conj
intersección : conj conj  conj
eliminar : conj ent  conj
cardinal : conj  ent
atomo : ent  conj
23
Especificación de tipos de datos
Ejemplo: conjuntos finitos de enteros
comportamiento
“Responde al modelo de los conjuntos
finitos de enteros”.
finEsp
24
Especificación de tipos de datos
Ejercicios:
Dar una especificación para:
 Las cadenas (finitas) de caracteres.
 Los números racionales.
 Polinomios con coeficientes enteros.
 Tabla de frecuencias absolutas.
25
Especificación de tipos de datos
Ejercicios:
Dar una especificación para:
 Agenda personal (fecha, hora y tarea).
 Ventas discográficas (utilizando tipos
para autores y discos).
 Baraja de cartas española.
26
Implementación de tipos de datos
El usuario (los programas) que utilizan
un tipo de datos sólo se fijan en la
especificación. Se supone que la
realización de ese tipo en la máquina
satisface la especificación (responde al
comportamiento que se fija en ella).
27
Implementación de tipos de datos
Implementación de un TAD:
 Representación: representar los datos de
los dominios en términos de datos de tipos
“más concretos”, que se suponen ya
implementados.
 Operadores: dar programas que
implementen los operadores (basados en
operadores de los “tipos concretos” de la
representación) que sean coherentes con el
comportamiento esperado.
28
Implementación de tipos de datos

El esquema es:
Modelo A
Alto nivel, abstracto
Función de abstracción
Modelo A’
Bajo nivel, concreto
29
Implementación de tipos de datos

Función de abstracción:
 : Modelo A’
Modelo A
“Modelo de bajo
nivel”
“Modelo abstracto”
Ejemplo: representación de pilas de enteros
…
v=
17
n=
4
-3
0
8
…

8
0
-3
17
30
Implementación de tipos de datos
Ejemplo: implementar los conjuntos finitos de
enteros (con operaciones vacío, estáVacio,
pertenece, unión, intersección, eliminar, cardinal,
átomo).

Implementación 1:
Representación:
v vector de enteros
 v , n  con 
n número entero positivo
(puede haber repetidos)
31
Implementación de tipos de datos
Función de abstracción:
1
 k  Ζ i  1,..., n tq v [i ]  k 
 v , n  
¿Implementación de los operadores?

Implementación 2:
Representación:
 v , n  con n  0 y sin repetidos
Función de abstracción:
1
 v [1], v[2],..., v[n]
 v , n  
¿Implementación de los operadores?
32
Implementación de tipos de datos
La función de abstracción:
 Puede ser parcial (no tiene que estar
definida sobre todos los datos de bajo
nivel).
 Puede no ser sobreyectiva.
 Puede no ser inyectiva.
 Debe “conmutar con los operadores”.
33
Implementación de tipos de datos
Ejercicios: especificar (sólo signatura) y
diseñar implementaciones para:
 pilas y colas
 listas de enteros con posición
 doble colas
 montículos y colas con prioridad
34
Implementación de tipos de datos
Ejercicios: especificar (sólo signatura) y
diseñar implementaciones para
 baraja de cartas española
 cartón de bingo
 monedero
35
Bibliografía


R. Peña. “Diseño de programas: formalismo
y abstracción”. Prentice Hall, 1997.
R.D. Tennent. “Specifying software”.
Cambridge University Press, 2002.
36
Tema 3: Tipos abstractos y
orientación a objetos.
Especificación y Desarrollo de Sistemas de Software
Universidad de La Rioja
Ana Romero Ibáñez
Contenidos del tema
1. Comentar la importancia de la noción
de TAD para la programación a
mediana/gran escala.
2. Mostrar mediante ejemplos cómo
trasladar especificaciones de TADs a
clases Java.
2
Importancia de los TADs


La programación con TADs es la base
para el diseño modular.
La estrategia fundamental para
diseñar programas de tamaño
medio/grande es la descomposición
en módulos (piezas
“cuasiindependientes” en que se
descompone una aplicación).
3
Importancia de los TADs
Requisitos para un módulo:
 Conexiones sencillas (y pocas) con el
resto de módulos.
 Tamaño razonable.
 Descomposición que facilite futuras
modificaciones y ampliaciones.
4
Importancia de los TADs
Un TAD es un buen candidato a módulo:
 Las conexiones vienen dadas por la
especificación (son pocas y sencillas).
 El tamaño suele ser adecuado
(representación + colección de
procedimientos y funciones).
 Se puede cambiar la implementación
sin que afecte al funcionamiento de los
demás módulos.
5
Importancia de los TADs

Los TADs suponen una
“generalización natural” del método de
los refinamientos sucesivos
(añadiendo el refinamiento a nivel de
tipos).
Idea del método:
“deja para mañana lo que puedas hacer hoy”
6
Importancia de los TADs

La programación con TADs permite el
uso de tipos genéricos (o
parametrizados), lo que resulta de
gran utilidad para construir programas
generales con alto grado de usabilidad
(con la flexibilidad que produce la
instanciación de los parámetros).
7
Importancia de los TADs
Problemas de los TADs:
 No hay un mecanismo para la
inicialización y finalización automática
de un tipo dado.
 No hay una forma sencilla de ampliar
una abstracción de datos añadiendo
operaciones nuevas.
8
TADs y Prog. Orientada a Objetos
Los dos problemas anteriores se solucionaron
con la idea de clase, la noción fundamental del
paradigma de programación orientada a
objetos.
POO= TADs + herencia
+ polimorfismo
+…
9
TADs y Prog. Orientada a Objetos
¿Cómo pasar de un TAD a una
clase Java?

No hay un método que
funcione siempre.

No hay una solución única.
10
TADs y Prog. Orientada a Objetos
Ejemplo 1: (fácil)
Especificación EMPLEADO
usa CADENA, BOOLEANO, ENTERO
género empleado
operadores
creaEmpleado : cad ent ent  empleado
nombre : empleado  cadena
activo : empleado  bool
sueldo : empleado  ent
numHijos : empleado  ent
descuento : empleado  ent
incrementarSueldo : empleado ent  empleado
modificarNombre : empleado cad  empleado
modificarActivo : empleado bool  empleado
finEspec
constructor
observadores
modificadores
11
TADs y Prog. Orientada a Objetos
¿Cómo sería la versión Java?
clase Empleado
Empleado (String s, int numHijos, int sueldo)
String getNombre ( )
boolean getActivo ( )
int getSueldo ( )
int getNumHijos ( )
int descuento ( )
void incrementarSueldo (int cantidad)
void modificarNombre (String cadena)
void modificarActivo (boolean estado)
constructor
observadores
modificadores
12
TADs y Prog. Orientada a Objetos


Parece que, salvo para el constructor,
basta con eliminar los argumentos de
tipo empleado en todas las cabeceras.
Esto va a ser así en muchos casos,
PERO no siempre la transformación
es tan directa.
13
TADs y Prog. Orientada a Objetos
Ejemplo 2: (no sale tan directo)
Especificación LISTACONPOSICION
usa NATURAL, BOOLEANO, TELEMENTO
género listacp
operadores
vacía :  listacp
añadir : listacp telemento nat  listacp
eliminar : listacp nat  listacp
elementoEn : listacp nat  telemento
estaVacia : listacp  bool
longitud : listacp  nat
concatenar : listacp listacp  listacp
finEspec
14
TADs y Prog. Orientada a Objetos
¿Cómo sería la versión Java?
clase ListaCP
ListaCP ( )
ClaseElemento elementoEn (int posicion)
boolean estaVacia ( )
int longitud ( )
void anadir (ClaseElemento e, int posicion)
void eliminar (int posicion )
constructor
observadores
modificadores
¿Y qué hacemos con “concatenar”?
15
TADs y Prog. Orientada a Objetos
Varias opciones para “concatenar”:

ListaCP concatenar (ListaCP lista1,ListaCP lista2)
Método de clase (static)

ListaCP concatenar (ListaCP lista)
Concatena lista al objeto y devuelve un objeto nuevo

void concatenar (ListaCP lista)
Método de instancia (cambia el estado del objeto
concatenándolo con otra lista)
16
TADs y Prog. Orientada a Objetos
Varias opciones para la clase ListaCP:

interfaz con una (o varias) clases que lo
implementen.
El método concatenar no podría ser estático.

clase abstracta, con todos los métodos
abstractos excepto concatenar (que se puede
construir a partir de los anteriores), y una (o
varias) clases que extiendan esa clase e
implementen los métodos.
17
TADs y Prog. Orientada a Objetos
Ejercicios: diseñar la versión orientada a
objetos (Java) de los TADs
 Pila y cola
 Doble cola
 Cola con prioridad y montículo
18
TADs y Prog. Orientada a Objetos
Ejercicios: diseñar un TAD y pensar en
la versión orientada a objetos (Java) de
 Mesa del juego del dominó
 Mesa del juego de la guerra
 Baraja de cartas española
 Agenda personal
19
Bibliografía




R. Peña. “Diseño de programas: formalismo y
abstracción”. Prentice Hall, 1997.
A. Tucker y R. Noonan. “Lenguajes de
programación. Principios y paradigmas”.
Mc Graw Hill, 2003.
F. Gutiérrez, F. Durán, E. Pimentel. “Programación
orientada a objetos con Java”. Thomson, 2007.
J. Lewis, J. Chase. “Estructuras de datos con Java.
Diseño de estructuras y algoritmos”. Pearson
Addison Wesley, 2006.
20
Tema 4: Especificación de
algoritmos
Especificación y Desarrollo de Sistemas de Software
Universidad de La Rioja
Ana Romero Ibáñez
Algoritmos y programas
Un algoritmo es la descripción precisa de una
sucesión de instrucciones que permiten llevar a
cabo un trabajo en un número finito de pasos.
Un buen algoritmo debe ser:




correcto,
eficiente,
reutilizable,
fácil de mantener.
Un programa es la codificación en un lenguaje de
programación concreto de un algoritmo.
2
Algoritmos y programas

A la hora de desarrollar un algoritmo,
podemos distinguir dos fases:




Especificar - ¿Qué hace? (de forma clara y precisa)
Implementar - ¿Cómo lo hace?
Un buen desarrollador debe garantizar que
ambas piezas queden bien separadas.
El usuario del programa sólo necesita
conocer la especificación (forma de usarlo y
significado).
3
Especificación de algoritmos
Para especificar un algoritmo podemos usar:
 Lenguaje natural
 Lenguaje formal (lógica de predicados)
¿Por qué especificar formalmente?
 Evitar ambigüedades
 Poder dar pruebas de corrección (testing no
garantiza la corrección).
4
Especif. con lenguaje natural
Ejemplo: el siguiente texto pretende
“especificar” el problema de la búsqueda en
un vector:
“Dado un vector y un elemento, decidir si
ese elemento está o no en el vector”
(
7
0
-4
23
…
, -4)
true
(
7
0
-4
23
…
, 9)
false
5
Especif. con lenguaje natural
Problemas: no se concreta
 tamaño del espacio de búsqueda
 ¿está ordenado el vector?
 ¿puede haber repetidos?
 ¿qué pasa si el vector está vacío?
 ¿puede haber cambios en los
parámetros?
 …
6
Especificación formal


Para escribir especificaciones claras y
precisas necesitamos un lenguaje
formal, con sintaxis y semántica
perfectamente definidos (el lenguaje
natural no es adecuado).
Usaremos lo que se denomina
Especificación Pre/Post.
7
Especificación formal
Notación: {Q} s {R}



Q (precondición): predicado que servirá para establecer
las condiciones que se exigen a los parámetros de
entrada.
R (postcondición): predicado que establece la relación
entre datos y resultados (entradas y las salidas).
s será una cabecera de tipo “acción” o “función”:

función nombre(x1:t1; ... ; xn:tn) devuelve (y1:t′1; ... ;
ym:t′m)

acción nombre(ent/sal x1:t1;…; ent/sal xn:tn; ent y1:t’1;
... ; ent ym:t’m)
8
Predicados
Un predicado será:
1) una fórmula atómica:
o
o
o
o
las constantes booleanas, cierto y falso;
una variable booleana, b;
expresiones aritméticas como 2∗x=y, a>0, i ≤ j...
una función matemática conocida, o especificada
formalmente, que devuelva un resultado booleano,
como primo(x), divide(x,y), vacia(p)…
2) una negación, ¬P, siendo P un predicado.
3) una conjunción, P  Q (P AND Q)
9
Predicados
Un predicado será:
4) una disyunción, P  Q (P OR Q)
5) un condicional P  Q
6) un bicondicional P  Q
7) un cuantificador universal, x.P(x)
8) un cuantificador existencial, x.P(x)
10
Especificación formal

Significado de {Q} s {R}:
“siempre que s se ejecuta
comenzando en un estado inicial que
verifica Q, el algoritmo termina y se
alcanza un estado que verifica R”
estado
inicial
.
s
{Q} s {R}
.
estado
final
11
Especificación formal


Si se parte de un estado que no verifica Q,
no es posible afirmar qué sucederá (puede
no terminar, terminar con un resultado
absurdo o terminar de forma razonable).
Las variables libres de Q estarán entre los
parámetros de entrada y entrada/salida. Las
variables libres de R estarán entre los
parámetros de entrada, salida y ent/sal.
12
Especificación formal
Ejemplo: problema de la búsqueda en
un vector
Constante MAX=200
Tipo tVector=Vector[1..MAX] de entero
{0  n  MAX}
función está? (v:tVector; n:entero; x:entero) devuelve
(b:booleano)
{b  x{v[1],…,v[n]})}
O también: {b  i{1..n}.(v[i]=x))}
13
Especificación formal
Respuestas a las preguntas no claras en la
especificación en lenguaje natural:
 Espacio de búsqueda: [1..n]
 En principio no está ordenado el vector.
 Puede haber repetidos.
 Admitimos el caso n=0. Devuelve falso.
 Por ser función, podemos garantizar que no
se van a producir cambios sobre los
parámetros reales.
14
Especificación formal
Ejemplos y ejercicios:

Mínimo de dos números enteros
{ } //Es lo mismo que poner Q  true
función mínimo (x:entero; y:entero) devuelve (m:entero)
{(m  x)  (m  y)  ((m=x)  (m=y))}
O también: {((m=x)  (m  y))  ((m=y)  (m  x}

Potencia de exponente natural
{n  1}
función potencia (x:real; n:entero) devuelve (pot:real)
n

{pot=x ∗ … ∗ x}
O también {pot=
n
 x}
i 1
15
Especificación formal

Cociente y resto de la división de dos
números naturales
{(divid  0)  (divis 0)}
función divisiónEntera (divid:entero; divis:entero)
devuelve (coc:entero; resto:entero)
{(divid=divis ∗ coc + resto)  (0  resto  divis)}

Frecuencia de aparición de un dato en un
vector de enteros
{0  n  MAX}
función frecuencia (v:tVector; n:entero; x:entero)
devuelve (f:entero)
1 si v [i ]  x
{f    (i ) donde  (i )  
}

v
i
x
0
si
[
]
i 1

n
Notación
:
n
f N (v [i ] x)
i1
16
Especificación formal

Máximo de un vector de enteros
{1  n  MAX} (pensar por qué n no puede ser igual a 0)
función máximoVector (v:tVector; n:entero)
devuelve (max:entero)
{(i  {1..n}.(max  v[i]))  (i  {1..n}.(max=v[i]))}

Cambiar en un vector todas las apariciones
Se añade en la precondición para cada
de un valor por otro
parámetro de ent/sal para poder hacer
referencia a su valor inicial
{(0  n  MAX)  (v=V)}
acción sustituir (ent/sal v:tVector; ent n:entero;
ent x:entero; ent y:entero)
{(i  {1..n}.((V[i]=x  v[i]=y)  (V[i]  x  v[i]=V[i]))}
17
Especificación formal

Decidir si un vector está ordenado en
orden creciente
{0  n  MAX}
función ordenCreciente (v:tVector; n:entero)
devuelve (b:booleano)
{b  (i  {1..n-1}.(v[i]  v[i+1]))}

Ordenar un vector
Se añade en la precondición para cada
parámetro de ent/sal para poder hacer
referencia a su valor inicial
{(0  n  MAX)  (v=V)}
acción ordenar (ent/sal v:tVector; ent n:entero)
{ordenCreciente(v,n)  (i  {1..n}.(frecuencia(V,n,V[i])=
frecuencia(v,n,V[i])))}
18
Especificación formal

Decidir si en un vector de booleanos hay más
true que false (usar frecuencia)
{0  n  MAX}
función gananVerdaderos (v:tVector; n:entero)
devuelve (b:booleano)
{b  frecuencia(v,n,true) > frecuencia(v,n,false))}

Añadir un dato a un vector
{(0  n < MAX)  (v=V)  (n=N)}
acción añadir (ent/sal v:tVector; ent/sal n:entero; ent x:entero)
{(n=N+1)  (frecuencia(v,n,x)=frecuencia(V,N,x)+1) 
(i  {1..n}.((v[i]  x)  (frecuencia(v,n,v[i])=
frecuencia(V,N,v[i])))}
No estoy exigiendo
19
nada sobre el orden
Especificación formal

Añadir un dato a un vector ordenado
{(0  n MAX)  ordenCreciente(v,n)  (v=V)  (n=N)}
acción añadirOrd (ent/sal v:tVector; ent/sal n:entero; ent x: entero)
{(n=N+1)  (frecuencia(v,n,x)=frecuencia(V,N,x)+1) 
(i  {1..n}.((v[i]  x)  (frecuencia(v,n,v[i])=
frecuencia(V,N,v[i])))  ordenCreciente(v,n)}

Eliminar todas las apariciones de un dato en
un vector
No estoy exigiendo
nada sobre el orden
{0  n  MAX  (v=V)  (n=N)}
acción eliminar (ent/sal v:tVector; ent/sal n:entero; ent x:entero)
{(n=N-frecuencia(V,N,x))  (frecuencia(v,n,x)=0) 
(i  {1..n}.(frecuencia(v,n,v[i])=frecuencia(V,N,v[i])))}
20
Especificación formal




Calcular la imagen especular de un vector.
Eliminar de un vector de enteros todas las
componentes que superen un determinado
valor.
Modificar un vector de enteros cambiando
cada una de sus componentes por 0 ó 1
según sea par o impar (usar los predicados
EsPar y EsImpar).
Modificar un vector de enteros duplicando
cada una de sus componentes.
21
Especificación formal




Dados dos vectores de enteros, decidir si
todos los elementos del primero están en el
segundo.
Dado un vector de enteros, sin elementos
repetidos y no vacío, eliminar su máximo.
Dados dos vectores de enteros, decidir si
uno de ellos es permutación del otro.
Dado un vector de enteros ordenado,
modificarlo para eliminar todas las
componentes negativas (manteniendo el
orden).
22
Bibliografía


R. Peña. “Diseño de programas: formalismo
y abstracción”. Prentice Hall, 1997.
R.D. Tennent. “Specifying software”.
Cambridge University Press, 2002.
23
Tema 5: Sintaxis y semántica de
un lenguaje imperativo sencillo
Especificación y Desarrollo de Sistemas de Software
Universidad de La Rioja
Ana Romero Ibáñez
Ideas sobre la corrección


En este tema vamos a ver una serie de
reglas básicas que nos van a permitir
probar la corrección (verificar formalmente)
de algunos algoritmos.
Un algoritmo con especificación {Q}s{R}
será correcto si:
siempre que se ejecuta comenzando en
un estado que verifica Q, el programa
termina y se llega a un estado que
satisface R
2
Ideas sobre la corrección

El programa estará formado por una
secuencia de instrucciones:
P  s1;…;sn

Para dar la corrección de {Q}s{R},
consideramos predicados que determinan
los estados válidos en los puntos
intermedios del programa, denominados
asertos o aserciones.
{Q}s1{P1}s2{P2}…{Pn-1}sn{R}
3
Ideas sobre la corrección


{Q=P0}s1{P1}s2{P2}…{Pn-1}sn{Pn=R}
Si el aserto inicial Q (precondición) se
satisface, y cada “programa” elemental sk,
consistente en una sola instrucción,
satisface su especificación {Pk-1}sk{Pk},
entonces se satisface finalmente la
postcondición y el programa es correcto.
Necesitamos reglas para decidir si una
instrucción elemental s satisface una
especificación dada {Q}s{R}.
4
Ideas sobre la corrección


Para cada instrucción elemental del
lenguaje, daremos una regla o axioma que
se usará para probar la corrección de
especificaciones básicas donde aparezca
esa sentencia.
Al conjunto de todos esos axiomas o reglas
se le denomina semántica axiomática del
lenguaje.
5
Ideas sobre la corrección

Las reglas o axiomas tendrán la forma:
premisas
conclusiones
donde las premisas y las conclusiones son
predicados o especificaciones de algoritmos.
El axioma garantiza que si se cumplen las
<premisas> entonces son ciertas las
<conclusiones>.
6
Sentencia de asignación


Sintaxis: var = expres
Semántica:
true
{R [expres|var] } var = expres {R}
r
a
v
Sustituir en R todas
las apariciones libres
de la variable var por
expres. También lo
puedo denotar R expres
Idea intuitiva:
para que al realizar una asignación var = expres
se satisfaga un predicado R, antes de hacerla
se debe satisfacer el mismo predicado R, pero
sustituyendo todas las apariciones libres de
var por expres.
7
Sentencia de asignación
Ejemplos:
 Calcular una precondición válida para:
{Q}={¿?}
x=x+8
{R}={x>10}

R[x+8|x]  (x+8 >10)  (x >2)
Solución: Q  x > 2
Calcular una precondición válida para:
{Q} ={¿?}
x=y-3
R[y-3|x]  ((z  0) AND ((y<z) OR (y  3)))
{R}={(z  0) AND ((y<z) OR (x  0))}
Solución: Q  z  0) AND ((y<z) OR (y  3))
8
Sentencia de asignación

Calcular una precondición válida para:
{Q}={¿?}
n=y-1
{R}={ n  {1..x} tal que y=2n }
Aquí no hay que sustituir nada
porque la aparición de la variable n
en la postcondición es ligada
Solución: Q  n  {1..x} tal que y=2n
9
Composición secuencial


Sintaxis: s1;s2 ó s1
s
2
Semántica:
{Q}s1{P} {P}s2{R}
{Q}s1;s2{R}
Idea intuitiva:
si sé que partiendo de un estado que satisface Q, al ejecutar s1 se
llega a un estado que verifica P, y que si parto de un estado que
verifica P, al realizar s2 se llega a un estado que verifica R,
entonces si parto de Q y ejecuto la composición secuencial s1;s2
llegaré a un estado que verifica R.
10
Composición secuencial
Ejemplos:
 Calcular una precondición válida para:
{Q}={¿?}
y=x+3
x=x-1
{R}={(x<0) AND (x  y)}
1)
Según el axioma de la asignación para la sentencia x=x-1:
P  R[x-1|x]  R xx-1 ((x<1) AND (x-1  y))
2)
Tomo lo anterior como postcondición para la primera
asignación y vuelvo a aplicar el axioma:
Solución: Q  x<1
Q  Pyx 3 ((x<1) AND (x-1  x+3))  x<1)
11
Composición secuencial

Calcular una precondición válida para:
{Q}={¿?}
x=x-5
y=x+3
{R}={(0  x  y) AND Par(y)}
1)
Axioma de la asignación para la sentencia y=x+3:
x 3
P  R[x+3|y]  Ry ((0  x  x+3) AND Par(x+3))
 ((0  x) AND Par(x+3))
2)
Vuelvo a aplicar el Axioma para la primera asignación:
Q  Pxx 5 ((0  x-5) AND Par(x-2))  ((5  x) AND Par(x))
Solución: Q  5  x) AND Par(x) 12
Sentencia condicional


Sintaxis: si B entonces sentEnt
si_no sentSiNo
fsi
Semántica:
Axioma 1
{B AND Q} sentEnt {R}
{(NOT B) AND Q} sentSiNo {R}
{Q} si B ………. fsi {R}
13
Sentencia condicional
Idea intuitiva del Axioma 1:
si somos capaces de encontrar un predicado Q que cumpla que:
 si se cumple Q y B entonces tras hacer lo que marque la rama
entonces se llega a R, y
 si se cumple Q y NOT B entonces tras hacer lo que marque la
rama si_no se llega a R,
entonces el axioma garantiza que, si se cumple Q, tras ejecutarse
el condicional se llega a R.
Problema:
necesitamos un predicado Q que nos sirva para las dos ramas del
condicional. En la práctica resulta más fácil el siguiente Axioma 2,
que es equivalente al anterior.
14
Sentencia condicional
Axioma 2
{Q1} sentEnt {R}
{Q2} sentSiNo {R}
{(Q1 AND B) OR (Q2 AND (NOT B))} si B ………. fsi {R}
Idea intuitiva del Axioma 2:
Si tenemos una precondición Q1 para la rama entonces y otra Q2 para
la rama si_no, podemos tomar {(Q1 AND B) OR (Q2 AND (NOT B))}
como precondición del condicional.
Queda una precondición complicada, pero es más fácil de calcular
que con el Axioma 1.
15
Sentencia condicional
Ejemplo:
 Calcular una precondición válida para:
{Q}={¿?}
si (x<1) entonces
y=x
si_no
y=y+1
x=x-1
fsi
{R}={x  y}
1)
Rama entonces:
{Q1}={¿?}
y=x
{R}= {x  y}
Q1  Ryx (x  x)  true
16
Sentencia condicional
2)
Rama si_no:
{Q2}={¿?}
y=y+1
x=x-1
{R}= {x  y}
2
1
y 1
Q2  Py (x-1  y+1) (x  y+2)
P  R xx 1 (x-1  y)
Según el Axioma 2, una precondición válida será
Q=(Q1 AND B) OR (Q2 AND (NOT B)). En nuestro caso:
Q=((x<1) OR ((x  y+2) AND (x  1)))
17
Sentencia condicional
Ejercicio:
 Calcular una precondición válida para:
{Q}={¿?}
si (x<0) entonces
x=x+1
si_no
x=x-1
fsi
{R}={x  0}
18
Condicional degenerado


Sintaxis: si B entonces
sentEnt
fsi
Semántica:
{Q1} sentEnt {R}
{(Q1 AND B) OR (R AND (NOT B))} si … sentEnt fsi {R}
19
Composición iterativa


Sintaxis: mientras que B hacer
cuerpo
fmq
Semántica:
No es sencillo dar una regla que permita
calcular la precondición a partir de la
postcondición. Se necesita definir un
predicado especial denominado invariante.
20
Composición iterativa: Invariante


Invariante: predicado lógico P que tiene la
propiedad de ser cierto antes de entrar en el
bucle, tras cada iteración y después del
bucle.
Idea: las variables cambian su valor dentro
del bucle, pero se mantienen invariantes
ciertas relaciones entre ellas (suele reflejar
la idea con la que se ha diseñado el bucle).
21
Composición iterativa: Invariante


El invariante P debe cumplir:
{P  B} cuerpo {P}
es decir, si P se cumple y entra en el bucle
(se cumple B), tras realizar el “cuerpo del
bucle” se vuelve a cumplir P.
Si somos capaces de garantizar que el
bucle termina, a la salida del bucle se
cumplirá {P  ¬B}.
22
Composición iterativa
Ejemplo:
 Buscar el invariante del bucle:
i=0; q=0; p=1;
mientras que (i < n) hacer
i=i+1
q=q+p
p=p+2
fmq
i
q
p
0 1 2 3 4 5
0 1 4 9 16 25
1 3 5 7 9 11
Invariante: P  ((0 ≤ i ≤ n)  q=i2  p=2*i+1)
(Intuimos que) se cumple {P  (i<n)} cuerpo {P}
23
Composición iterativa
Ejemplo:
 Buscar el invariante del bucle (factorial):
i=0
f=1
mientras que (i < n) hacer
i++
f=f*i
fmq
i
f
Iteración
0 1 2 3 4
5
1 1 2 6 24 120
Invariante: P  ((0 ≤ i ≤ n)  (f=i!))
Al salir se cumple f=n!
24
Composición iterativa
¿Cómo pruebo que P  ((0 ≤ i ≤ n)  (f=i!)) es un invariante?
{P  B}
i++
f=f*i
{P}
Tengo una composición secuencial de dos asignaciones.
1)
Precondición válida para la primera asignación:
H  P ff * i  ((0 ≤ i ≤ n)  (f*i=i!))
2)
Precondición válida para la segunda asignación:
Q  H ii  1  ((0 ≤ i+1 ≤ n)  (f * (i+1)=(i+1)!))
Como P  B  Q, se cumple {P  B} cuerpo {P}
25
Composición iterativa
Ejemplo:
 Buscar el invariante del bucle (búsqueda
secuencial):
b=falso; i=1
mientras que (i ≤ n) hacer
si (v[i]=x) entonces
b=cierto
fsi
i++
fmq
P  ((b  x{v[1],…,v[i-1]}) AND (1 ≤ i ≤ n+1))
¿Es invariante?
26
Composición iterativa
Pruebo que P ((b  x{v[1],…,v[i-1]}) AND (1 ≤ i ≤ n+1)) es un
invariante:
{P  B}
si (v[i]=x) entonces b=cierto
fsi
i++
{P}
Tengo una composición secuencial de un condicional y una
asignación.
Precondición
para la asignación:
i1
H  Pi ((b  x{v[1],…,v[i]}) AND (1 ≤ i+1 ≤ n+1))
Precondición para la rama entonces:
Q1  H bcierto ((cierto  x{v[1],…,v[i]}) AND (1 ≤ i+1 ≤ n+1))
27
Composición iterativa
Precondición para la rama si_no: Q2=H
Precondición para el condicional:
(Q1 AND B) OR (H AND (NOT B))  Q 
((x{v[1],…,v[i]}) AND (1 ≤ i+1 ≤ n+1) AND (v[i]=x))
OR
((b  x{v[1],…,v[i]}) AND (1 ≤ i+1 ≤ n+1)) AND (v[i]  x))
Faltaría ver que P  B  Q
(Q es más débil que P  B)
28
Composición iterativa
Con la noción de invariante ya podemos dar la semántica
(axioma) para la composición iterativa:
{P  B} cuerpo {P}
{P} mientras que B… fmq {P AND (NOT B)}
Idea intuitiva:
si el predicado P sirve como invariante del bucle, el axioma nos asegura que si
llegamos al bucle y se cumple P, a la salida del bucle se cumple P AND (NOT B)
Para hacer la corrección de algoritmos
habrá que asegurar que el bucle termina
(probar que la condición B llega a fallar)
29
Otras estructuras iterativas
Nota:
Para las estructuras iterativas
repetir cuerpo hasta B
para i desde E1 hasta E2 hacer cuerpo fpara
para i bajando desde E1 hasta E2 hacer cuerpo fpara
pueden encontrarse programas equivalentes
basados en una estructura “mientras que”
(no hace falta dar axiomas).
30
Otros dos axiomas para la
semántica

Fortalecer la precondición:
{Q’}s{R} Q  Q’
{Q}s{R}

Debilitar la postcondición
{Q}s{R’} R’  R
{Q}s{R}
31
Bibliografía


R. Peña. “Diseño de programas: formalismo
y abstracción”. Prentice Hall, 1997.
A. Tucker y R. Noonan. “Lenguajes de
programación. Principios y paradigmas”.
Mc Graw Hill, 2003.
32
Tema 6: Verificación formal de
la corrección de algoritmos
Especificación y Desarrollo de Sistemas de Software
Universidad de La Rioja
Ana Romero Ibáñez
Corrección de algoritmos
n
En este tema vamos a hacer pruebas
completas de corrección de
algoritmos, utilizando las reglas
(axiomas) vistos en el Tema 5 para las
distintas instrucciones elementales del
lenguaje.
2
Corrección de algoritmos
n
Nos vamos a “limitar” a programas que
respondan al siguiente esquema:
{Q}
<inicializar>
mientras que B hacer
<cuerpo>
fmq
devuelve (<var>)
{R}
3
Corrección de algoritmos
n
En realidad esto no supone ninguna
restricción:
¡
¡
Si hay varios bucles “hermanos” puede
pensarse que los otros están en
<inicializar>.
Si hay bucles anidados puede pensarse
que los bucles internos están en
<cuerpo>.
4
Esquema para
la corrección de algoritmos
n
Según la axiomática, para verificar un
programa que tenga el esquema dado
hace falta:
1. Encontrar un invariante P para el bucle.
2. Probar que se cumple {Q}<inicializar>{P}.
3. Probar que P es invariante, es decir:
{P ∧ B} <cuerpo> {P}.
4. Probar que {P ∧ NOT(B)} es más fuerte que
la postcondición {R}.
5. Asegurar que el bucle termina.
5
Ejemplo
Potencia de exponente natural:
Q ≡ {n ≥ 0}
función potencia (x:real; n:entero) devuelve (pot:real)
variables i: entero; pot: real
principio
i=0
pot = 1
mientras que (i<n) hacer
pot = pot ∗ x
i++
fmq
devuelve (pot)
fin
n
∪
R ≡ {pot=x ∗ … ∗ x} ≡ {pot=xn}
6
Ejemplo
1.
Encontrar un invariante P para el bucle:
Tomo P ≡ (0 ≤ i ≤ n) AND (pot=xi)
2.
Probar que se cumple {Q}<inicializar>{P}:
H i0 ≡ (0 ≤ 0 ≤ n) AND (1=x0) ≡ (0 ≤ n) ≡ Q
{¿?}
2
1
i=0
1
H ≡ Ppot ≡ (0 ≤ i ≤ n) AND (1=xi)
pot=1
{P}= {(0 ≤ i ≤ n) AND (pot=xi)}
4.
Probar que {P ∧ NOT(B)} es más fuerte que la
postcondición {R}:
P ∧ NOT(B) ≡ (0 ≤ i ≤ n) AND (pot=xi) AND (i ≥ n)
≡ (i=n) AND (pot=xi) → (pot=xn ) ≡ R
7
Ejemplo
5.
Asegurar que el bucle termina:
“La variable i crece y n se mantiene luego i llegará a
igualar o superar a n y entonces se saldrá del bucle”.
3.
Probar que P es invariante: {P ∧ B} <cuerpo> {P}
pot*x
{¿?}
2
J ≡ H pot ≡ (0 ≤ i+1 ≤ n) AND (pot*x=xi+1)
pot = pot ∗ x
i +1
1
H ≡ Pi ≡ (0 ≤ i+1 ≤ n) AND (pot=xi+1)
i++
{P}
P ∧ B ≡ (0 ≤ i ≤ n) AND (pot=xi) AND (i<n) → J, luego se
tiene {P ∧ B} <cuerpo> {P}
8
Ejemplos
Especificar, diseñar y probar la
corrección de algoritmos que permitan
n
calcular el factorial de un número
natural
n
decidir si un elemento está o no en
un vector (búsqueda secuencial)
9
Ejemplos
Especificar, diseñar y probar la
corrección de algoritmos que permitan
n
calcular la raíz cuadrada entera de un
número entero positivo
n
calcular la suma de las componentes
de un vector de enteros
10
Bibliografía
n
n
R. Peña. “Diseño de programas: formalismo
y abstracción”. Prentice Hall, 1997.
A. Tucker y R. Noonan. “Lenguajes de
programación. Principios y paradigmas”.
Mc Graw Hill, 2003.
11
Descargar