Está en la página 1de 40

ESPECIFICACIÓN DE

ALGORITMOS
Tema 1
1. Introducción
Tema 1. 2. Estados, asertos
Especificación 3. Especificación Pre/Post (tripleta
de algoritmos de Hoare)
4. Especificación de un TAD

2
¿Por qué hay que especificar?

■ Es muy difícil obtener programas completamente correctos:


– Dificultades vinculadas al lenguaje de programación.
– Dificultades relacionadas con la lógica del programa.
■ El software comercial se distribuye con errores (bugs).

■ Probar los programas es necesario, pero no es suficiente. En


general, es imposible probar exhaustivamente todas las
situaciones que se pueden dar en el programa.

■ Es importante definir claramente, a nivel lógico, qué debe hacer


cada algoritmo o función contenido en el programa.
– Permite verificar si la función hace lo que estaba previsto.
– Facilita el desarrollo a la persona que lo implementa.

Estructuras de datos y algoritmos (TEMA 1) 3


¿Qué hay que especificar?

■ Para verificar un algoritmo es necesario especificar el


comportamiento esperado del mismo. Para ello, hay que definir 3
elementos:
1. Datos suministrados (parámetros de entrada).
2. Resultados esperados (parámetros de salida).
3. Relación entre ellos.

■ Al conjunto de estos elementos se le denominará especificación.

Estructuras de datos y algoritmos (TEMA 1) 4


¿Cómo especificar?

■ Una especificación puede realizarse de manera informal,


mediante lenguaje natural.
– Por ejemplo, como comentario de una función.
– El lenguaje natural es ambiguo y por tanto, pueden haber
diferentes interpretaciones.

■ Puede realizarse mediante lenguajes formales.


– Existe una única interpretación.
– El lenguaje formal es más complicado de usar.

Estructuras de datos y algoritmos (TEMA 1) 5


EJEMPLO:
ESPECIFICACIÓN
INFORMAL DE FUNCIONES

Estructuras de datos y algoritmos (TEMA 1) 6


const int N = 10;

typedef int Vector[N];

/**********************************************************
* Funcion Inicializa
Especificación * Pone el valor inicial de todos los elementos del vector a 0
*
informal * Parametros:
* v E y S vector
**********************************************************/
void Inicializa(Vector v)
{
int i;

for(i = 0; i < N; i++)


v[i] = 0;
}

Ejemplo
/**********************************************************
* Funcion Suma
* Suma dos vectores
*
Especificación * Parametros:
informal * v1 E vector a sumar
* v2 E vector a sumar
* vres S vector resultado
*
**********************************************************/
void Suma(Vector v1, Vector v2, Vector vres)
{
int i;

for(i = 0; i < N; i++)


vres[i] = v1[i] + v2[i];
}

Estructuras de datos y algoritmos (TEMA 1) 7


1. Introducción
Tema 1. 2. Estados, asertos
Especificación 3. Especificación Pre/Post (tripleta
de algoritmos de Hoare)
4. Especificación de un TAD

8
Estados

■ Estado de un algoritmo (función/programa) =


Descripción completa de los valores asociados a todas las
variables del algoritmo en un momento determinado de su
ejecución.

■ Ejecutar una instrucción supone modificar el estado de un


algoritmo  la ejecución es una sucesión de estados.
– Ejemplo:
Algoritmo Intercambia(x,y: Entero) dev x, y: Entero
Auxiliar: z: Entero
z ← x
x ← y
y ← z
FIntercambia

Estructuras de datos y algoritmos (TEMA 1) 9


Ejemplo

Intercambia (1,3) Estado de “Intercambia”


x y z
1 3 ?
z← x → 1 3 1

Ejemplo
x ←y → 3 3 1

y ←z → 3 1 1

FIntercambia

Estructuras de datos y algoritmos (TEMA 1) 10


Asertos

■ Aserto = Predicado (expresión booleana) que expresa un conjunto


de estados de un programa.
– Podemos vincular un aserto a un punto del programa,
indicando que en ese punto son válidos los estados que
cumplen el aserto (= true, satisface el aserto).
– Si no se satisface el aserto algo está mal porque estaremos
en un estado no previsto.

■ Ejemplo: si x >= 1 entonces x ← x – 1

si x >= 1 entonces
{x >= 1} Aserto = “El programa debe estar en cualquier estado donde x >= 1”
x ← x – 1
{x >= 0} Aserto = “El programa debe estar en cualquier estado donde x >= 0”

Estructuras de datos y algoritmos (TEMA 1) 11


Definición formal de asertos:
Cuantificadores
■ Cuantificador = abreviatura de una secuencia de operaciones
análogas.
■ Cuantificadores que vamos a utilizar para especificar asertos:
Suma de todos los valores tomados por E(α), cuando α
Σ𝛼𝛼 : dominio: E(𝛼𝛼) recorre todos los valores del dominio = ∑𝛼𝛼𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖 𝐸𝐸(𝛼𝛼)
Producto de E(α), cuando α recorre todos los valores del
Π𝛼𝛼 : dominio: E(𝛼𝛼)
dominio = ∏𝛼𝛼𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖𝜖 𝐸𝐸(𝛼𝛼)

∀𝛼𝛼 : dominio: B(𝛼𝛼) Para todo valor α del dominio se cumple B(α)

∃𝛼𝛼 : dominio: B(𝛼𝛼) Existe un valor α del dominio para el que se cumple B(α)
Valor natural que indica el número de valores α del
Ν𝛼𝛼 : dominio: B(𝛼𝛼)
dominio para los que se cumple B(α)
Mayor valor tomado por E(𝛼𝛼), cuando α recorre todos los valores
max 𝛼𝛼 : dominio: E(𝛼𝛼)
del dominio
Menor valor tomado por E(𝛼𝛼), cuando α recorre todos los valores
min 𝛼𝛼 : dominio: E(𝛼𝛼)
del dominio

Estructuras de datos y algoritmos (TEMA 1) 12


EJEMPLOS DE ASERTOS

Estructuras de datos y algoritmos (TEMA 1) 13


Ejemplo Σ Π

■ Suponer que la variable v está declarada como un vector (array)


de enteros con índices entre 0 y N-1, entonces:

Σ𝛼𝛼 : 0≤ 𝛼𝛼 < N : v[𝛼𝛼]


■ Denota el entero resultante de sumar todos los valores del vector

Ejemplo
v.

Π𝛼𝛼 : 0≤ 𝛼𝛼 < N : v[𝛼𝛼]


■ Denota el entero resultante de multiplicar todos los valores del
vector v.

Estructuras de datos y algoritmos (TEMA 1) 14


Ejemplo ∀ ∃

∀𝛼𝛼 : 0≤ 𝛼𝛼 < N : (v[𝛼𝛼] = 0)


■ Denota un valor booleano que será cierto si todos los valores del
vector v son iguales a 0, y falso en caso contrario.

∃𝛼𝛼 : 0≤ 𝛼𝛼 < N : (v[𝛼𝛼] = 0)

Ejemplo
■ Denota un valor booleano que será cierto si, y solo si, algún
elemento del vector v es igual a 0, y falso en caso contrario.

Estructuras de datos y algoritmos (TEMA 1) 15


Ejemplo Ν max min

Ν𝛼𝛼 : 0≤ 𝛼𝛼 < N : (v[𝛼𝛼] = 0)


■ Denota un valor natural que indica cuántos elementos del vector
v son iguales a 0.

max 𝛼𝛼 : 0≤ 𝛼𝛼 < N : v[𝛼𝛼]

Ejemplo
■ Denota el mayor valor que contenido en el vector v.

min 𝛼𝛼 : 0≤ 𝛼𝛼 < N : v[𝛼𝛼]


■ Denota el menor valor que contenido en el vector v.

Estructuras de datos y algoritmos (TEMA 1) 16


Definición de asertos: Variables

■ Las variables de los asertos pueden ser de los siguientes tipos:


– Ligadas:
■ Están vinculadas al cuantificador (letras griegas)

– Libres:
■ Variables de programa: denotan el último valor que se les haya
asignado (letras minúsculas)
■ Variable iniciales: denotan el valor de una variable en un punto
concreto del programa (letras mayúsculas).
– Las constantes son un caso particular de este tipo de variables.
■ Ejemplo ( P indica el código de una función ):
{x = X л y = Y} Aserto = “x tiene un valor X e y tiene un valor Y”
P ¿Qué hace P?
{x = Y л y = X} Aserto = “x tiene un valor Y e y tiene un valor X”

Estructuras de datos y algoritmos (TEMA 1) 17


Utilidad de los Asertos

■ Especificar el comportamiento esperado del programa.

■ Calcular/Verificar el comportamiento real del programa.

■ Documentar el programa.

Estructuras de datos y algoritmos (TEMA 1) 18


1. Introducción
Tema 1. 2. Estados, asertos
Especificación 3. Especificación Pre/Post (tripleta
de algoritmos de Hoare)
4. Especificación de un TAD

19
Especificación Pre/Post

■ C.A.R. Hoare escribió en 1969:


“Programación es una ciencia exacta en la que todas las
propiedades de un programa y todas las consecuencias de
ejecutarlo en un ambiente dado, pueden ser determinadas, en
principio, a partir del texto mismo del programa a través de
razonamiento inductivo puro”

■ Presentó un sistema axiomático para razonar sobre la corrección


de programas mediante el uso de asertos.
– Tripleta de Hoare: {P}S{Q}
■ {P} Precondición {y≠0} x ← 1/y {x=1/y}
■ S Programa { } a ← b {a=b}
■ {Q} Postcondición {x≥0} y ← sqrt(x) {x=y*y}
■ https://youtu.be/tAl6wzDTrJA?t=134
– https://youtu.be/tAl6wzDTrJA?t=777
Estructuras de datos y algoritmos (TEMA 1) 20
Especificación de funciones

■ Cabecera: Nombre de la función, nombre y tipo de los parámetros


de entrada y nombre y tipo de los resultados (parámetros de
salida).
■ Precondición: Aserto (previo) que se debe cumplir para que la
función se pueda ejecutar con garantías de funcionamiento
correcto.
– Solo puede hacer referencia a los parámetros de entrada.
■ Postcondición: Aserto (posterior) que se cumplirá cuando la
función acabe.
– Relaciona los resultados con los parámetros de entrada.

■ Significado de la especificación:
– “Si al empezar a ejecutarse la función se cumple la
precondición, al acabar necesariamente tiene que cumplirse
la postcondición.”

Estructuras de datos y algoritmos (TEMA 1) 21


Especificación formal de funciones

■ Incorporar asertos que especifiquen:


– Precondición y Postcondición

■ Ejemplos:
func Inicializa(v: Vector[1..N] de ℕ) dev v: Vector[1..N] de ℕ
{Pre: cierto}
{Post: ∀α: 1 <= α <= N: v[α] = 0}

func Suma(v1, v2: Vector[1..N] de ℕ)


dev vres: Vector[1..N] de ℕ
{Pre: cierto}
{Post: ∀α: 1 <= α <= N : vres[α] = v1[α] + v2[α] }

Estructuras de datos y algoritmos (TEMA 1) 22


Ejercicios

1. Especificación de una función que calcule el cociente y resto de


una división entera entre valores naturales.

2. Especificación de una función que devuelva el máximo de un


vector.

Ejemplo
3. Especificación de una función que devuelva la posición del
máximo de un vector.

Estructuras de datos y algoritmos (TEMA 1) 23


1. Especificación de una función que calcule el cociente y
resto de una división entera entre valores naturales.

func dividir (a, b: ℕ) dev c,r: ℕ


{ Pre: b≠0 }
{ Post: (a=b*c+r) л (r<b) }

Ejemplo
Estructuras de datos y algoritmos (TEMA 1) 24
2. Especificación de una función que devuelva el máximo
de un vector.

func maximo (a: vector[1..N] de ℝ) dev m: ℝ


{ Pre: N>0 }
{ Post: m = max 𝛼𝛼 : 1 ≤ 𝛼𝛼 ≤ N : a[𝛼𝛼] }

Ejemplo
o bien,

{ Post: (∀𝛼𝛼 : 1 ≤ 𝛼𝛼 ≤ N : (m ≥ a[𝛼𝛼] )) л


(∃𝛽𝛽 : 1 ≤ 𝛽𝛽 ≤ N : (m = a[𝛽𝛽])) }

Estructuras de datos y algoritmos (TEMA 1) 25


3. Especificación de una función que devuelva la posición
del máximo de un vector.

func pos_maximo (a: vector[1..N] de ℝ) dev pos: ℕ


{ Pre: N>0 }
{ Post: (m = max 𝛼𝛼 : 1 ≤ 𝛼𝛼 ≤ N : a[𝛼𝛼]) л (a[pos]=m) л
(1 ≤ pos ≤ N) }

Ejemplo
o bien,

{ Post: (∀𝛼𝛼 : 1 ≤ 𝛼𝛼 ≤ N : (a[pos] ≥ a[𝛼𝛼] )) л


(1 ≤ pos ≤ N) }

Estructuras de datos y algoritmos (TEMA 1) 26


Escribir programas con asertos
■ Se debe incluir la precondición y la postcondición de una función (programa)
como documentación en el código fuente .
– Especifican claramente la tarea a realizar, fijando los estados del
programa para los cuales el funcionamiento de la función será correcto.

■ Precondición: Es útil incluir instrucciones que comprueben su validez:


– Fase de desarrollo (depuración)  Muy recomendable (obligatorio).
– Versión de producción  Eliminar estas comprobaciones o reconvertir
en Excepciones (funciones de interfaz para clases, módulos, etc.).

■ Postcondición:
– Fase de desarrollo (depuración)  Opcional incluir comprobaciones
(totales o parciales).
– Versión de producción  Eliminar estas comprobaciones.

■ ¿Los lenguajes de programación tienen herramientas para automatizar y


facilitar el uso de asertos?
– Sí.

Estructuras de datos y algoritmos (TEMA 1) 27


Asertos en C++

■ Existe la macro assert(int test) , que permite especificar un


aserto y que el precompilador expande automáticamente a una
sentencia if ( ! test ).
– Si test es falso, el programa “aborta”.

■ Se tiene que incluir el fichero de cabecera <assert.h>

■ Si antes de incluir la librería se define la constante NDEBUG


(#define NDEBUG) los asertos no tienen efecto.

■ Existen bibliotecas no estándar para el uso de asertos y test de


programas: Gnu Nana, Boost Test Library, Google Test, etc...

Estructuras de datos y algoritmos (TEMA 1) 28


Ejemplo: División entera (assert)

// Descomentar #define para que los assert no se ejecuten


// #define NDEBUG
#include <assert.h>

int Div(int a, int b, int & r)


{
int c;

Ejemplo
// Pre:
assert(a >= 0 && b > 0);

c = a / b;
r = a % b;

// Post:
assert( (c >= 0) && (r >= 0) && (a == b*c + r) && (r < b) );

return c;
}

Estructuras de datos y algoritmos (TEMA 1) 29


Ejemplo: División entera (tras
precompilador)
int Div(int a, int b, int & resto)
{
int c;

// Pre:
if ( !(a >= 0 && b > 0) )
{
(void)fprintf(stderr, "Assertion failed: file \"%s\", line
%d\n", __FILE__, __LINE__);

Ejemplo
exit(1);
}

c = a / b;
resto = a % b;

// Post:
if ( !((a == b*c + resto) && (resto >= 0) && (resto < b) ) )
{
(void)fprintf(stderr, "Assertion failed: file \"%s\", line
%d\n", __FILE__, __LINE__);
exit(1);
}

return c;
}
Estructuras de datos y algoritmos (TEMA 1) 30
1. Introducción
Tema 1. 2. Estados, asertos
Especificación 3. Especificación Pre/Post (tripleta
de algoritmos de Hoare)
4. Especificación de un TAD

31
Especificación de un TAD

■ Un TAD especifica las operaciones que se pueden realizar y la


semántica de dichas operaciones. Es independiente de la
implementación.
■ La especificación de los TAD que vamos a utilizar se denomina
especificación algebraica o ecuacional.
■ La especificación consta de tres partes: dominio, signatura de las
operaciones y ecuaciones (axiomas).
– Dominio: Especificación de los tipos implicados en la
definición.
– Signatura: Sección donde se declaran los identificadores y
operaciones que se van a utilizar. (Sintaxis)
– Ecuaciones: Describen el comportamiento de las operaciones
para cualquier posible valor de entrada. (Semántica)

Estructuras de datos y algoritmos (TEMA 1) 32


Ejemplo

Formato utilizado para la signatura de las operaciones:


nombre_operacion : tipos de entradas -> tipos de salidas
Tipo contador
Dominio:
contador: Conjunto de objetos contadores
ℬ: Conjunto de valores lógicos = {cierto, falso}
Operaciones:

Ejemplo
cero : -> contador
Operaciones generadoras =
incr : contador -> contador Se puede obtener un objeto de
decr : contador -> contador cualquier valor
si_cero : contador -> ℬ

Ecuaciones: ∀ x: contador
1) decr(incr(x)) ≡ x
2) si_cero(cero) ≡ cierto
3) si_cero(incr(x)) ≡ falso
Ecuaciones de error:
func decr(x: contador) dev y: contador
4) decr(cero) ≡ error {Pre: x≠cero}

Estructuras de datos y algoritmos (TEMA 1) 33


Evaluar composición de operaciones

■ Las ecuaciones permiten evaluar expresiones sobre el tipo.


■ Ejemplo:
si_cero(incr(incr(decr(incr(decr(incr(cero)))))))  ?
– si_cero(incr(incr(decr(incr(decr(incr(cero))))))) =
si_cero(incr(x)), siendo
– x = incr(decr(incr(decr(incr(cero)))))
– ¿Es x un contador válido o genera un error?
– Aplicando ec.1:
■ incr(decr(incr(decr(incr(cero))))) =
incr(decr(incr(cero)))
– Aplicando ec.1:
■ incr(decr(incr(cero))) = incr(cero)
– incr(cero) es un contador válido, por tanto,
■ si_cero(incr(x)), siendo x = incr(cero)
■ Aplicando ec.3: si_cero(incr(x)) = falso

Estructuras de datos y algoritmos (TEMA 1) 34


Ejemplo: Tipo Pila

■ Pila: Lista LIFO = Secuencia de elementos donde el primer


elemento eliminado será el último elemento introducido.
■ Especificación TAD:

Ejemplo
Tipo Pila
𝐸𝐸: Tipo de elementos contenidos en una pila
pila: Conjunto de pilas que contienen elementos de 𝐸𝐸
ℬ: Conjunto de valores lógicos = {cierto, falso}
ℕ: Conjunto de números naturales
Operaciones:
p_nueva: → pila Operaciones generadoras
apilar: 𝐸𝐸, pila → pila
desapilar: pila → pila
cima: pila → 𝐸𝐸
vacia: pila → ℬ
tamaño: pila → ℕ

Estructuras de datos y algoritmos (TEMA 1) 35


TAD Pila (cont.)

Ecuaciones: ∀ p:pila; ∀ x:𝐸𝐸


1) desapilar(apilar(x,p)) ≡ p
2) cima(apilar(x,p)) ≡ x
3) vacia(apilar(x,p)) ≡ falso
4) vacia(p_nueva) ≡ cierto
5) tamaño(p_nueva) ≡ 0
6) tamaño(apilar(x,p)) ≡ 1 + tamaño(p)

Ejemplo
Ecuaciones de Error:
7) desapilar(p_nueva) ≡ error Precondiciones en:
8) cima(p_nueva) ≡ error • desapilar
• cima

Estructuras de datos y algoritmos (TEMA 1) 36


Ejemplo: Tipo Pila

■ Ejercicio 1: Decir cual será la pila resultante de las siguientes


operaciones:
cima(desapilar(apilar(3,apilar(1,apilar(2,p_nueva)))))

■ Ejercicio 2: Definir las ecuaciones para una nueva operación (¿son

Ejemplo
iguales dos pilas?):
igual: pila, pila → ℬ

Estructuras de datos y algoritmos (TEMA 1) 37


Ejercicio 1: Evaluar expresión

cima(desapilar(apilar(3,apilar(1,apilar(2,p_nueva)))))

(Ec. 1) = cima(apilar(1,apilar(2,p_nueva)))

(Ec. 2) = 1

Ejemplo
Estructuras de datos y algoritmos (TEMA 1) 38
Ejercicio 2: Definir las ecuaciones

igual: pila, pila → ℬ


■ igual(p_nueva, p_nueva) ≡ cierto
■ igual(p_nueva, apilar(y,q)) ≡ falso
■ igual(apilar(x,p), p_nueva) ≡ falso
■ igual(apilar(x,p), apilar(y,q)) ≡

Ejemplo
(x=y) л igual(p,q)

Estructuras de datos y algoritmos (TEMA 1) 39


Ejercicio propuesto

■ Especificar una función que sume todos los elementos de una


Pila de Naturales.

func f_suma(p: Pila de Nat) dev s: Nat


{Pre: cierto }

Ejemplo
{Post: ?? }

Estructuras de datos y algoritmos (TEMA 1) 40

También podría gustarte