Vous êtes sur la page 1sur 48

Captulo 1

Especicacin de problemas
1.1 Introduccin
El diseo formal de algoritmos utiliza mtodos formales para abordar sus tres fases fundamentales: especicacin, derivacin y vericacin. La especicacin formal de algoritmos es una tcnica que permite especicar la semntica intencional de un algoritmo de forma breve y precisa. A partir de una especicacin formal se pueden deducir formalmente (derivar) las instrucciones que debe contener el algoritmo y, una vez escrito, vericar formalmente su correccin. La vericacin formal de algoritmos tiene una gran importancia ya que permite vericar la correccin de un algoritmo antes de ser escrito en un lenguaje concreto (lenguaje de implementacin). Es lo que se conoce como vericacin a priori. Tradicionalmente los algoritmos se prueban, una vez escritos, con la ayuda de herramientas de depuracin, es lo que se conoce como vericacin a posteriori. Esto quiere decir que, hasta que no se prueba el programa no aparecen los errores. Al igual que en otra muchas actividades, cuanto ms pronto aore un error menos esfuerzo costar el corregirlo, lo que da un gran valor a las tcnicas formales de especicacin, derivacin y vericacin. La vericacin formal tambin se puede aplicar a algoritmos que no hayan sido derivados formalmente.

1.2 Especicacin formal con precondiciones y postcondiciones


El objetivo de toda especicacin de algoritmos, formal o no, es el de expresar de forma correcta y sin ambigedades qu es lo que debe hacer un algoritmo y bajo qu condiciones se puede ejecutar. Ejemplo: Escribir un algoritmo que realice la divisin de un entero a por otro entero b, distinto de cero, devolviendo el cociente entero por defecto en q y el resto en r. 1

CAPTULO 1.

ESPECIFICACIN DE PROBLEMAS

Fijndose en la especicacin del ejemplo se ve que tiene dos destinatarios: 1. El usuario que vaya a utilizar el algoritmo. En el ejemplo el usuario se tiene que cerciorar de que b tiene que ser distinto de cero. 2. El programador que tendr que desarrollar el algoritmo suponiendo que el usuario llamar al algoritmo con los parmetros adecuados. En el ejemplo, desarrollar el algoritmo suponiendo que b es distinto de cero. La tcnica de especicacin formal que se va a utilizar es la conocida como tcnica pre/post. Un algoritmo se especica siguiendo el siguiente esquema {Q}S {R}, que se leer de la forma siguiente: "Si S comienza su ejecucin en un estado que satisface Q, termina, y lo hace en un estado que satisface R" El signicado de los tres componente es el siguiente: que cumplir los parmetros de entrada para que el algoritmo produzca el resultado deseado. Es donde se expresan las obligaciones que debe cumplir el usuario. S es la interfaz del algoritmo. Donde se especica el nombre del algoritmo y sus parmetros formales de entrada y de salida. R es la postcondicin. Donde se especica la relacin que deben cumplir los parmetros de entrada y los de salida para que el algorimo produzca el resultado deseado. Es donde se expresan las obligaciones del programador. Tanto la precondicin como la postcondicin se especican mediante predicados lgicos. Un predicado lgico es una frmula cuya evaluacin solo puede dar dos resultados: Cierto o F also. En cuanto a la interfaz, la notacin que se utilizar ser
Q es la precondicin. Donde se especican las restricciones que tienen

fun f (x : Tx ) dev (y : Ty )
donde:
f representa al nombre de la funcin. x : Tx representa a los parmetros de entrada y sus correspondientes tipos. y : Ty representa a los parmetros de salida y sus correspondientes tipos.

Ejemplo: La especicacin pre/post del problema de la divisin es:


{Q b = 0} fun divisionEntera(a, b : entero) dev(q, r : entero) {R a = b q + r r < b r 0}

Cuando se quiera especicar una accin, la especicacin de la interfaz se har mediante la siguiente notacin

1.3.

LGICA DE PREDICADOS

accion f (x cf : Tx )
donde cf se concretar en:
E, para los parmetros de solo de entrada. S, para los parmetros de solo de salida. nada o E/S, para los parmetros de entrada y salida.

El ejemplo anterior especicado para una accin sera:


{Q b = 0} accion divisionEntera(a, b E : entero; q, r S : entero) {R a = b q + r r < b r 0}

1.3

Lgica de predicados
Es predicado Una constante booleana Una variable de tipo booleano Una expresin relacional Una funcin booleana Ejemplo

Un predicado lgico puede ser atmico o construirse utilizando operadores. Un predicado atmico puede ser:
verdadero,f also x,y x y, x + y > 0 esP ar(x), estaOrdenado(x)

Denotando por las letras P y Q a predicados y por D a un dominio de valores, adems de los predicados atmicos, son igualmente predicados los siguientes: Es predicado La negacin de un predicado Una conjuncin de predicados Una disyuncin de predicados Un condicional de predicados Un bicondicional de predicados Una cuanticacin universal de un predicado Una cuanticacin existencial de un predicado Ejemplo
P P Q P Q P Q P Q D.P () D.P ()

Los cuanticadores sirven para escribir de forma abreviada una operacin sobre todos los valores de un dominio. El universal para la conjuncin y el existencial para la disyuncin, de tal manera que: El predicado
D.P () D.P () P (d1 ) P (d2 ) ... P (dn ) P (d1 ) P (d2 ) ... P (dn )

siendo "" el operador para denotar la equivalencia de predicados y d1 , d2 ,....dn los n valores del dominio D.

CAPTULO 1.

ESPECIFICACIN DE PROBLEMAS

Adems de estos cuanticadores, se utilizarn otros para representar de forma abreviada operaciones aritmticas sobre todos los valores de un dominio. Estos cuanticadores son:

El predicado (Sumatorio) D.P () (Producto) D.P () N (Conteo) N D.P ()

P (d1 ) + P (d2 ) + ... + P (dn ) P (d1 ) P (d2 ) ... P (dn ) Nu mero(P (d1 ), P (d2 ), ..., P (dn ))

siendo la funcin Nmero igual al nmero de sus argumentos que se evalan a Cierto. Obsrvese que, en los dos primeros P () debe ser una frmula aritmtica y en el tercero una frmula lgica. Los cuanticadores podrn ser denotados por la notacin anterior o por, la utilizada tradicionalmente para los cuanticadores aritmticos:

b b b b b =a P (), =a P (), N=a P (), =a P (), =a P ()

1.3.1 Leyes de equivalencia de predicados

Las leyes de equivalencia que facilitan el clculo con predicados son las siguientes:

1.3.

LGICA DE PREDICADOS

Ley Conmutativa Conmutativa Asociativa Asociativa Idempotencia Idempotencia Distributiva Distributiva Absorcin Absorcin Elemento neutro Elemento neutro Elemento neutro Elemento neutro Negacin Negacin Negacin De Morgan De Morgan de de de de de de de ( y ) de de

Predicados equivalentes
P Q P Q P (Q R) P (Q R) P P P P P (Q R) P (Q R) P (P Q) P (P Q) P F also P F also P Cierto P Cierto P P P P P (P Q) (P Q) P Q P Q ( Di .P ) ( Di .P ) ( D.P ) ( D.P ) ( D.P ) D1 . D2 .P D1 . D2 .P QP QP (P Q) R (P Q) R P P (P Q) (P R) (P Q) (P R) P P F also P P Cierto P F also Cierto P Q P Q P Q (P Q) (Q P ) Cierto, si Di = F also, si Di = ( Di .P ) ( Di .P ) ( D.P [/]), siempre que / variables(P ) D2 . D1 .P D2 . D1 .P

1.3.2 Conceptos bsicos


Variables libres y ligadas En un predicado, se dice que una variable es ligada cuando est afectada por un cuanticador. Una variable es libre cuando no est afectada por un cuanticador. Por ejemplo, en la frmula x(x > z ) z (z x), en el primer operando x es ligada y z es libre y en el segundo z es ligada y x es libre. Es una buena prctica nombrar a las variables ligadas mediante letras griegas y a las libres mediante letras latinas. Por ejemplo, el predicado del ejemplo anterior se podra escribir ( > z ) ( x). Las variables libres corresponden a las variables del algoritmo. El papel de las variables ligadas es el de ayudar a describir aspectos sobre dominios de valores. Estas ltimas estn ligadas al cuanticador ms cercano. Un mismo identicador puede denotar distintas variables ligadas. Por ejemplo,

CAPTULO 1.

ESPECIFICACIN DE PROBLEMAS

en D1.(f ()) D2.(g ()) la variable ligada toma los valores del dominio D1 en el primer subpredicado y de D2 en el segundo.

Estado de una variable Es el valor que tiene la variable en un momento determinado de la ejecucin de un algoritmo. Estado de un algoritmo Es el valor que tienen todas sus variables libres en un momento determinado de su ejecucin. Aserto asercin Es un predicado que expresa la relacin que tienen que cumplir los valores de ciertas variables en un momento determinado de la ejecucin de un algoritmo. Los asertos los escribiremos como comentarios del algoritmo, por tanto el predicado deber escribirse entre los signos "{" y "}". La precondicin y la postcondicin son los asertos que se tienen que cumplir al inicio y a la nalizacin, respectivamente, del algoritmo. Podremos escribir tantos asertos entre las sentencias de un algoritmo como se considere conveniente y constituyen comentarios valiosos para la comprensin del algoritmo. Evaluacin de un predicado Para evaluar un aserto, ste tiene que estar bien denido. Se dice que el aserto {P } est bien denido si se puede evaluar para todos los posibles valores de las variables libres que aparecen en P y, adems, todas las funciones que aparecen en P estn bien denidas. Sustitucin e Se denota por Px al resultado de sustituir en la frmula de P todas las apariciones libres de la variable x por la expresin e. Esta expresin debe cumplir las siguientes restricciones: (1) no puede contener variables ligadas de P y (2) ha <e1 ,..,en > e se generaliza a P<x de ser del mismo tipo de dato que x. La notacin Px 1 ,..,xn > para representar al predicado resultado de sustituir en P simultneamente, las apariciones de x1 , .., xn por las expresiones e1 , .., en .
Ejemplo: Sea P (z ) z.((1 < z < d x mod z = 0) d < x), entonces z 5 z.((1 < z < d 5 mod z = 0) d < 5), sin embargo Px x no es Px una sustitucin vlida, ya que z es una variable ligada.

Predicados ms fuertes y ms dbiles Un predicado P dene un conjunto de estados, aquellos estados en que el predicado se evale como Cierto. Se dice que un predicado P es ms fuerte (ms restrictivo) que otro Q, si el conjunto de estados representados por P es un subconjunto de los estados representados por Q. Formalmente, si se denota por estados(X ) el conjunto de estados que satisfacen el predicado X , se dice que P es ms fuerte que Q si estados(P )

1.3.

LGICA DE PREDICADOS

estados(Q). De igual forma se dice que P es ms dbil que Q si estados(P ) estados(Q). La notacin P Q expresa que P es ms fuerte que Q y, viceversa, que Q es ms dbil que P . Tambin diremos que Q es una deduccin lgica de P .

Reforzamiento de un predicado Consiste en aadirle una conjuncin con otro predicado ( P Q P ). El predicado ms fuerte es F also ya que por mucho que se refuerce sigue siendo F also, (F also P F also) Debilitamiento de un predicado Consiste en aadirle una disyuncin con otro predicado. ( P P Q. Obviamente, si el predicado P es una conjuncin de predicados, cualquier predicado resultante de eliminar alguna de las conjunciones ser un debilitamiento de P . El predicado ms dbil es Cierto ya que por mucho que se debilite sigue siendo Cierto, (Cierto P Cierto). Otra forma de debilitar un predicado es realizar una sustitucin en el predicado de una constante por una variable, sta con un dominio de valores, donde la constante sea uno de los valores del dominio. En una especicacin pre/post se deben especicar la precondicin ms dbil y la postcondicin ms fuerte posibles. Axioma Es una propiedad que no necesita ser demostrada (a = a). Regla de inferencia Es una forma de deducir unas propiedades de otras que se suponen ciertas. La notacin que se emplear para enunciar una regla de inferencia es la sigu1 ,E2 ,...,En iente E F1 ,F2 ,...Fm , que se leer "si se cumplen (evalan a Cierto) E1 , E2 , ..., En , tambin se cumplirn F1 , F2 , ...Fm . Clculo de predicados Consiste en el razonamiento sobre predicados partiendo de la leyes de equivalencia (los axiomas) y de dos reglas de inferencia bsicas:
P2 ,P2 P3 Regla de transitividad. P1 P 1 P3
1 P2 Regla de sustitucin. Q(PP , siendo Q(P ) un predicado Q que 1 )Q(P2 ) tiene un subpredicado P .

Demostracin de la correccin de una deduccin lgica La demostracin de la correccin de una deduccin lgica P Q la podemos hacer, indistintamente, de tres formas bsicas:
1. Haciendo ver que el antecedente es ms fuerte que el consecuente. 2. Como cierto es el predicado ms dbil, evaluando el consecuente a cierto, aprovechando o no el cumplimiento de los predicados del antecedente.

CAPTULO 1.

ESPECIFICACIN DE PROBLEMAS

3. Realizando equivalencias y deducciones lgicas, partiendo del antecedente o parte de l, hasta llegar a un predicado que sea el mismo que el consecuente. Vamos a ver la aplicacin de las tres formas bsicas a un ejemplo sencillo,
x > 0 x < 100 x > 0

1. x > 0 x < 100 x > 0 es una deduccin (lgica) correcta, ya que el consecuente es un debilitamiento del antecedente. 2. Para que se cumpla el antecedente se tiene que cumplir x > 0, por tanto el consecuente se evala a cierto lo que hace que la deduccin sea correcta por ser cierto el predicado ms dbil. 3. Partiendo del predicado x > 0 del antecedente realizamos la siguiente deduccin lgica trivial x > 0 x > 0. La utilizacin de una u otra forma depender de la forma deduccin y de las preferencias particulares de cada uno.

1.4 Introduccin al diseo formal de algoritmos


Los pasos para disear un algoritmo son los siguientes: 1. Especicar la funcin o la accin que, como se ha visto, consiste en:
Especicar la interfaz de la funcin o de la accin:

 El nombre de la funcin o de la accin.  Sus parmetros formales. Especicar la precondicin. Especicar la postcondicin.
La especicacin se har utilizando la notacin {Q}S {R} 2. Derivar el algoritmo. 3. Vericar la correccin del algoritmo derivado.

1.4.1 Deniciones
En lo siguiente se denotar por C tanto una instruccin, como una secuencia de instrucciones , incluso, todo un algoritmo.

Correccin parcial Se dice que un cdigo C es parcialmente correcto con una precondicin Q y una postcondicin R, que se denota por {Q}C {R}, si comienza en un estado que satisface Q, en caso de que termine, lo hace en un estado que satisface R.

1.4.

INTRODUCCIN AL DISEO FORMAL DE ALGORITMOS

Correccin total Cuando C , adems de ser correcto parcialmente, termina. Relacin entre correccin parcial y total Si C no contiene bucles ni tiene recursividad y es correcto parcialmente, tambin lo es totalmente. En caso contrario, para demostrar la correccin total de C , adems de demostrar su correccin parcial, habr que demostrar que termina. Invariante de un bucle La derivacin y la vericacin de las instrucciones de un bucle se apoya en el concepto de invariante. Se llama invariante de un bucle a un aserto P que describe todos los estados por los que atraviesan las variables del bucle, observados justo antes de evaluar la condicin B de terminacin del bucle. Concretamente, el invariante se tiene que cumplir antes y despus de cada iteracin, en particular, antes de la primera y despus de la ltima. Por tanto, el invariante es, a la vez, precondicin y postcondicin del bucle.
Si por ejemplo, se tiene el siguiente segmento de cdigo
i := 0; q := 0; p := 1 mientras i < n hacer i := i + 1; q := q + p; p := p + 2 fmientras

si se listan los estados del algoritmo antes de cada iteracin se tendran los siguiente valores: estado
P0 P1 P2

. . .

0 1 2 . . .

0 1 4 . . .

1 3 5 . . .

se ver una forma de obtener el invariante de un bucle sin tener que listar los valores que iran tomando las variables.

q = i2 p = 2 i + 1. Este predicado sera el invariante del bucle. Ms adelante,

donde se ve que las variables cumplen la relacin expresada por el predicado

10

CAPTULO 1.

ESPECIFICACIN DE PROBLEMAS

Captulo 2

Diseo formal de algoritmos iterativos


2.1 El sistema formal de Hoare
Denotaremos por Dom(E ) al predicado que dena a todos los valores del dominio de las variables libres de E para los que sea posible evaluar E . Por ejemplo, siendo x e y enteros, la expresin x + y > 0 es evaluable para cualquier valor de x e y , sin embargo la expresin x/y no es evaluable cuando y es 0, por tanto Dom (x + y > 0) Cierto y Dom (x/y ) y = 0 El sistema formal de Hoare es un sistema de reglas de inferencia que permiten razonar sobre las instrucciones de un algoritmo, bien sea para calcularlas o para vericar su correccin. Estas reglas son las siguientes:

2.1.1 Reglas generales


Reglas de reforzamiento de la precondicin y debilitamiento de la postcondicin (o reglas de la consecuencia)
{Q}S {R}, Q Q , {Q }S {R} {Q}S {R}, R R {Q}S {R }

Sirven para introducir asertos ms fuertes/dbiles. La primera de estas reglas dice que siempre se puede fortalecer la precondicin y la segunda que siempre se puede debilitar la postcondicin.

Reglas de composicin de precondiciones y postcondiciones


{Q1 }S {R1 }, {Q2 }S {R2 } {Q1 Q2 }S {R1 R2 }, {Q1 Q2 }S {R1 R2 }

Esta regla dice que siempre se pueden componer las precondiciones y las postcondiciones si se hacen ambas con el mismo operador o . 11

12

CAPTULO 2.

DISEO FORMAL DE ALGORITMOS ITERATIVOS

2.1.2 Reglas de las instrucciones del lenguaje


Instruccin de asignacin
{At x }x := t{A}

Este regla dice que At x es precondicin para que la ejecucin de la instruccin x := t lleve a un estado que cumpla su postcondicin A. Dicho de otra forma, despus de ejecutarse una instruccin x := t, x satisface la misma propiedad que t satisfaca antes de la asignacin. Esta regla proporciona la forma de obtener la precondicin ms dbil de un segmento de cdigo. Se denotar por pmd(C, A), a la precondicin ms dbil que garantice que la ejecucin de C lleve a un estado que satisfaga A. Los siguientes son ejemplos de precondiciones ms dbiles.
{x + y = 10}x := x + y {x = 10} {j.(x = 2j )}z := x{j.(z = 2j )}. x+y En efecto, en el primero {x = 10}x x + y = 10 x y en el segundo {j.(z = 2j )}z j.(x = 2j )
t Q Rx {Q}x := t{R}

Adems, de esta regla y de la de reforzamiento de la precondicin se deduce la siguiente regla: que da la forma de demostrar la correccin de {A}C {B }, que consiste en demostrar la correccin de A pmd(C, B ).

Instruccin de composicin de instrucciones


{Q}S1 {P }, {P }S2 {R} {Q}S1 , S2 {R}

Esta regla sirve para razonar con secuencias de instrucciones. La regla dice que dos instrucciones S1 y S2 , en este orden, satisfacen una especicacin con precondicion Q y postcondicin R, si existe un aserto intermedio P , que sea postcondicin de la primera y precondicin de la segunda.

Instruccin de seleccin
{Q B }S1 {R}, {Q B }S2 {R} {Q Dom(B )}Si B entonces S1 si_no S2 fsi{R}

donde Dom(B ) es la expresin que dene el conjunto de estados en los que se puede evaluar la expresin B . Esta regla dice que para demostrar que la instruccin Si B entonces S1 si_no S2 fsi, satisface una especicacin con precondicion Q y postcondicin R, si se demuestra que son correctas

2.1.

EL SISTEMA FORMAL DE HOARE

13

{Q B }S1 {R} y {Q B }S2 {R}

La regla particularizada para una instruccin de seleccin con una rama vaca es:
{Q B }S {R}, Q B R {Q Dom(B )}Si B entonces S fsi{R}

2.1.3 Instrucciones iterativas


Un instruccin iterativa debe cumplir ciertas condiciones para que sea correcta totalmente. Llamando P al invariante, B a la condicin del bucle y S a las instrucciones del cuerpo del bucle, la primera condicin es la satisfaccin de la invarianza de P . La segunda, que en cada iteracin deber ser correcta P Dom(B ), ya que si no habra estados en que no sera evaluable B y, por tanto, abortara la ejecucin del algoritmo.

Funcin cota o limitadora de un bucle Las dos condiciones anteriores no garantizan que el bucle termine. Por tanto, adems, habr que asegurarse de la terminacin del bucle. Para ello, se tiene que encontrar una expresin del no de iteraciones que realiza el bucle, en funcin de algn estado de cmputo, y demostrar que:
1. Esa expresin se evala a un nmero entero positivo y, por tanto, tiene una cota inferior. 2. El valor de la expresin decrece estrictamente en cada iteracin. La bsqueda de esa expresin se basa en el concepto de f uncinlimitadora. Una funcin limitadora t : estado Z
es una funcin que a cada estado del algoritmo da un nmero entero, se mantiene no negativa en cada iteracin y decrece en cada iteracin.

Heurstica para encontrar una funcin limitadora


intervienen en la expresin de la condicin del bucle y que son modicadas en el cuerpo del bucle. La idea es que esa expresin debe dar una indicacin del nmero de iteraciones que quedan por realizar en una determinada iteracin. Esta expresin debe decrecer en cada iteracin. Se ajusta, si es necesario, para garantizar que es no negativa siempre que se cumpla P B .
Construir una expresin entera t con todas o algunas de las variables que

Instruccin Mientras

14

CAPTULO 2.

DISEO FORMAL DE ALGORITMOS ITERATIVOS

Teniendo en cuenta lo anterior, la regla para un bucle Mientras es


{P B }S {P }, P Dom(B ), P B t 0, {P B t = T }S {t < T } {P }Mientras B hacer S fmientras{P B }

Las reglas para los bucles Repetir hasta y Desde hasta Hacer no se formulan ya que ambos bucles se pueden transformar en un bucle Mientras.

2.2 Derivacin formal de algoritmos iterativos


Las ideas bsicas a seguir para derivar formalmente un algoritmo iterativo, partiendo de su especicacin formal son las siguientes: 1. 2. 3. 4. El punto de partida es la postcondicin. La precondicin juega un papel secundario. Se utilizan asertos intermedios para facilitar el proceso. La derivacin del algoritmo y su vericacin formal se desarrollan en paralelo. 5. La correccin es la que dirige el proceso.

2.2.1 Derivacin de instrucciones de asignacin


Para poder derivar una instruccin, por simple o compleja que sea, se tienen que conocer los asertos que se deben cumplir antes y despus de la ejecucin de dicha instruccin. Partiendo de este conocimiento, si I es una instruccin que debe hacer correcta la terna {A}I {B }, se sabe que I debe hacer correcta A pmd(I, B ) (ver la conclusin de la regla de asignacin). Derivacin de instrucciones simples de asignacin Si B tiene una expresin de la forma x = e, se prueba con la instruccin e x := e. Si se cumple A Bx , entonces esa es la instruccin que se necesita. Por ejemplo si se tiene que derivar la instruccin I en {x = X y = Y }I {x = Y y = X }, se plantea la deduccin x = X y = Y pmd(I, x = Y y = X ). Si se propone I < x, y >:=< Y, X >, la deduccin queda x = X y = Y pmd(< x, y >:=< Y, X >, x = Y y = X ), es decir, aplicado la denicin que se ha dado del predicado pmd queda x = X y = Y {x = Y y = X }<Y,X> <x,y> , operando x = X y = Y Y = Y X = X . Luego, al evaluarse el consecuente a cierto, la deduccin es correcta. Por tanto la propuesta de I es correcta. Derivacin de instrucciones complejas de asignacin Cuando, partiendo del mismo planteamiento del punto anterior, la propuesta de I no sirve, hay que ver qu condiciones adicionales e instrucciones son necesarias. El razonamiento a seguir se va a ilustrar con el siguiente ejemplo:

2.2.

DERIVACIN FORMAL DE ALGORITMOS ITERATIVOS

15

{x = X y = Y AB = u + xy }I {x = X div 2 y = 2 Y AB = u + xy } siguiendo un planteamiento similar al del punto anterior. Se plantea la deduccin x = X y = Y AB = u + xy pmd(I, x = X div 2 y = 2 Y AB = u + xy ), si se propone I < x, y >:=< X div 2, 2 Y >, la deduccin queda x = X y = Y AB = u + xy pmd(< x, y >:=< X div 2, 2 Y >, x = X div 2 y = 2 Y AB = u + xy ),

Supngase que se quiere derivar I en

es decir,
x = X y = Y AB = u + xy div {x = X div 2 y = 2 Y AB = u + xy }<X <x,y>
2 ,2 Y >

, operando queda

simplicando queda

x = X y = Y AB = u + xy X div 2 = X div 2 2 Y = 2 Y AB = u + (X div 2) 2 Y , que x = X y = Y AB = u + xy AB = u + (X div 2) 2 Y , y operando AB = u + XY AB = u + (X div 2) 2 Y , es decir se tendra que cumplir

en el antecedente queda que

XY = (X div 2) 2 Y

Al ser div la divisin entera esa igualdad solo se cumple cuando X es par. Cuando X es impar se sabe que (X div 2) 2 = X 1. Es decir, en caso de ser impar, se cumplir que XY = (X div 2) 2 Y + Y . Luego, si se suma Y a la variable u se cumplira que: u + XY = (u + Y ) + (X div 2) 2 Y , que es la igualdad que quedara para demostrar que la instruccin I necesaria, en caso de que X fuese impar, es < x, y, u >:=< X div 2, 2 Y, u + Y > Es decir, la conclusin de este razonamiento es que la instruccin I necesaria se concretara en:

Si X es par entonces <x,y>:= <X div 2,2* Y> si no <x,y,u>:= <X div 2,2* Y,u+Y> fsi.
Esta instruccin se puede simplicar en la siguiente:

Si X es impar entonces

16

CAPTULO 2.

DISEO FORMAL DE ALGORITMOS ITERATIVOS

u:= u+Y> fsi <x,y>:= <X div 2,2* Y>

2.2.2 Derivacin de bucles


El esquema de bucle que se va a utilizar para su derivacin es el siguiente:
{Q} Inic 1 mientras B 2 Restablecer {T } Avanzar 3 fmientras 4 {R } hacer{P }

donde:
Q es la precondicin de las sentencias anteriores al bucle, que se denotan

por Inic . R es la postcondicin del bucle. P es el invariante del bucle. B es la condicin de entrada en el cuerpo del bucle. El cuerpo del bucle est constituido por las instrucciones denotadas por:

 Avanzar que representa a las instrucciones que hacen que las variables que intervienen en la expresin B avancen hacia la condicin de salida del bucle, es decir hacia B .  Restablecer que representa a las instrucciones que modican las variables libres del invariante no modicadas por Avanzar.
T es un aserto intermedio, que habr que calcular una vez concretada Avanzar, cuya utilidad es facilitar el clculo de Restablecer.

Para no repetir la escritura del invariante P , en los puntos donde se debe cumplir: 1,2,3 y 4, ste se escribir una sola vez a continuacin de la palabra clave hacer. Adems del invariante, en los siguientes puntos se deber cumplir:
En el 2, B , es decir P B .

2.2.

DERIVACIN FORMAL DE ALGORITMOS ITERATIVOS

17

En el 4, B , es decir P B .

Derivacin de bucles a partir de invariantes Se recomienda seguir los siguientes pasos:


1. Obtener el invariante P y la condicin de terminacin del bucle B , de tal manera que sea correcta P B R. 2. Obtener B: (B ). 3. Inic: deber garantizar {Q}Inic{P }. Suelen ser asignaciones de expresiones triviales a las variables libres del invariante que no sean parmetros de entrada, que hagan que se cumpla el invariante. 4. Obtener el cuerpo del bucle:
Avanzar : partiendo del valor asignado a las variables en Inic, ver de que forma hay que modicar las que aparecen en B para hacer que vayan hacia unos valores que hagan que se cumpla B . Restablecer : Construir un aserto T que haga correcta {T }Avanzar{P }. Es decir T pmd(Avanzar, P ). Como tambin debe hacer que sea correcta {P B }Restablecer{T }

 Si P B T , entonces no es necesaria Restablecer.  Si no, proponer que el resto de la variables libres de P se modiquen asignndoles unas expresiones que habr que calcular. Para ello se plantea la deduccin P B pmd(Restablecer, T ) y se ve cmo tienen que ser esas expresiones para que la deduccin sea correcta. Derivacin de bucles en secuencia y anidados
Si se necesitan varios bucles, se deriva cada uno por separado. Si se necesitan bucles anidados, se deriva cada uno por separado em-

pezando desde el ms externo hacia el ms interno.

Heurstica para obtener invariantes a partir de la postcondicin Se basa en las propiedades que se deben cumplir:
Cuando termina el bucle, se cumplir P B y tambin R, por tanto P B R. Mientras se itera, algunos estados de P no pertenecern a R. Por lo que la idea es que debilitando R se puede llegar a P .

La heurstica propiamente dicha es la siguiente:


Si R ya est en forma conjuntiva, es decir R R1 R2 :

 Se toma como P el operando, R1 R2 , en el que sea ms fcil dar valores a sus variables libres que hagan que se cumpla, y el otro como B .

18

CAPTULO 2.

DISEO FORMAL DE ALGORITMOS ITERATIVOS

Si R no est en forma conjuntiva:

 Construir R1 , sustituyendo en R expresiones (suelen ser constantes) por nuevas variables w. Si se hace que R2 sea la ecuacin de sustitucin w = (x), se cumplir que R R1 R2 . Se toma R2 como B y R1 Dom(w) como P .
El siguiente ejemplo ilustra la derivacin de algoritmos iterativos.

fun Suma(n : integer) dev(r : integer)


R r = n =0

Qn0

1. Postcondicin en forma conjuntiva Como, en este caso, R no est en forma conjuntiva, se sustituye en ella la constante n por la variable x. Por tanto R r = x =0 x = n. El dominio de x ser 0 x n. Con lo hecho hasta ahora:
el invariante ser P r = x =0 0 x n y la condicin de salida del bucle B x = n.

2. Obtencin de la condicin del bucle B (B ) (x = n) x = n, pero teniendo en cuenta el dominio de x se puede dejar como x<n. 3. Obtencin de Inic Inic debe hacer correcta {n 0}Inic{r = x =0 }. Se ve que los valores de las variables libres de P (x y r ) que hacen que ste se cumpla son 0, en ambas. Por tanto se propone que Inic se concrete x:=0;r:=0. Es obvio que: <0,0> n 0 {r = x =0 0 x n}<x,r> , ya que al evaluarse la parte derecha como Cierto, n 0 Cierto es una deduccin correcta. 4. Obtencin de Avanzar Como el bucle termina cuando x = n y x se inicializa a 0, parece razonable suponer que en cada iteracin se incremente el valor de x en 1. Por lo que se propone x:= x+1. 5. Obtencin de Restablecer Previamente se calcula T .
x+1 T pmd(Avanzar, P ) pmd(x := x + 1, P ) Px +1 x+1 r = x r = x =0 0 x n}x =0 0 x + 1 n.

Como no es correcta la deduccin:

2.2.

DERIVACIN FORMAL DE ALGORITMOS ITERATIVOS

19

x+1 r = x =0 0 x n r = =0 0 x + 1 n, ser necesaria la instruccin Restablecer.

Ya que Avanzar modica x, parece razonable suponer que Restablecer modique la otra variable, r, asignndole un valor que se expresa por Er , es decir, tendr la forma r := Er .
Er pmd(Restablecer, T ) pmd(r := Er , T ) Tr +1 Er = x =0 0 x + 1 n. Er Luego debe ser correcta P B Tr , es decir, x+1 r = x =0 0 x n x < n Er = =0 0 x + 1 n.

Dndose cuenta que r = x =0 , si se hace que Er sea igual r + x + 1, la deduccin


x+1 r = x =0 0 x n x < n r + x + 1 = =0 0 x + 1 n, es

una deduccin correcta.

En efecto, si se sustituye r en el consecuente, ste queda


x+1 x =0 + x + 1 = =0 0 x + 1 n

e introduciendo x + 1 en el sumatorio
+1 x+1 x =0 = =0 0 x + 1 n,

Cierto 0 x + 1 n Cierto ya que la expresin 0 x + 1 n es Cierta porque en el antecedente de la deduccin se tiene que 0 x n x < n 0 x < n, y es evidente que 0 x < n 0 x + 1 n es una deduccin correcta.

Con lo que Restablecer se concreta en la instruccin r:=r+x+1. Con todo lo anterior el algoritmo obtenido ser el siguiente:
{Q n 0}

func suma (n :entero) dev(r :entero)


x := 0; r := 0; mientras x < n hacer {P r = x =0 0 x n} r := r + x + 1; x := x + 1

fmientras un

{R r = n =0 }

20

CAPTULO 2.

DISEO FORMAL DE ALGORITMOS ITERATIVOS

2.3 Vericacin formal de algoritmos iterativos


La vericacin formal de un algoritmo iterativo se basa en la aplicacin de las reglas vistas anteriormente. La estrategia de la vericacin se basa en dividir el algoritmo en partes y vericar por separado cada una de ellas (aplicacin de la regla de composicin de instrucciones). Para ilustrar la vericacin de algoritmos iterativos, sta se centrar en algoritmos que sigan el siguiente esquema.
{Q} Inic

mientras B hacer{P }
Restablecer {T } Avanzar

fmientras
{R } F in {R }

ya que es sucientemente representativo. Si el algoritmo fuese ms complejo:


si tuviese varios bucles en secuencia, se utilizaran predicados intermedios

y se vericarn por separado, si tuviese bucles anidados, se vericara el ms interior y se tratara como una caja negra en el bucle externo superior.

Un aspecto crucial para la vericacin es encontrar el invariante del bucle, si ste no viene ya dado. Las ideas bsicas que guan esta bsqueda son las siguientes:
Debe ser sucientemente fuerte para que junto con B lleve a R . Debe ser sucientemente dbil para que Inic haga que se cumpla y despus de la ejecucin de S se mantenga la invarianza.

Los pasos para vericar un algoritmo iterativo son los siguientes: 1. Obtencin de la postcondicin del bucle El punto de partida es R.
Si F in no tiene contenido entonces R R. Si lo tiene, R pmd(F in, R).

2. Proponer el invariante y la funcin de cota del bucle En el caso de que no vengan dados. Para ello se utilizan las mismas heursticas presentadas en derivacin.

2.3.

VERIFICACIN FORMAL DE ALGORITMOS ITERATIVOS

21

3. Satisfaccin de la postcondicin del bucle Comprobar que cuando se sale del bucle se llega a un estado que satisface R ,(P B R ). 4. Satisfaccin inicial del invariante Comprobar el cumplimiento del invariante a la llegada al bucle ({Q}Inic{P }). 5. Mantenimiento de la invarianza en cada iteracin Comprobar de que despus de cada iteracin se mantiene la invarianza ({P B }S {P }). 6. Cota inferior positiva Comprobar que la funcin cota tiene una cota inferior (P B t 0). 7. Decrecimiento del nmero de iteraciones Comprobar que el bucle termina ({P B t = T }S {t < T }). Aunque los pasos 3, 4, 5, 6 y 7 se pueden realizar en cualquier orden, conviene probar primero los pasos 3 y 4 (los lmites del bucle). Si falla la vericacin de los pasos 3 y 4, suele ser porque el invariante no es el apropiado. Ejemplo: Vericar el siguiente algoritmo que resuelve el problema de la suma de los n primeros nmeros naturales.

fun suma(n : entero) dev(r : entero) Mientrasx < n hacer {P }


r := r + x + 1; {T } x := x + 1 x := 0; r := 0;

{Q n 0}

fmientras un

{R r = n =0 }

1. Obtencin de la postcondicin del bucle Como F in no tiene contenido R R . 2. Proponer el invariante La obtencin de la funcin limitadora t se pospone hasta la vericacin de los puntos 6 y 7. Teniendo en cuenta que, al ser B x < n e incrementarse en 1 x en cada iteracin, la condicin de salida del bucle B ser x = n, por lo que se propone que:
P r = x i=0 i 0 x n

22

CAPTULO 2.

DISEO FORMAL DE ALGORITMOS ITERATIVOS

3. Satisfaccin de la postcondicin del bucle


P B R , es decir,
n r = x =0 0 x n x = n r = =0 .

Operando en el antecedente,
n r = x =0 0 x n x = n r = =0 0 n n,

donde se ve que el antecedente es ms fuerte que el consecuente; por tanto, la deduccin es correcta. 4. Satisfaccin inicial del invariante
{Q}Inic{P }). En este caso,

habr que demostrar la correccin de Q pmd(Inic, P ).


pmd(Inic, P ) pmd(x := 0; r := 0, P )
0 0 0 0 {{r = x =0 0 x n}r }x {r = =0 0 0 n}r

0 = 0 =0 0 0 n 0 = 0 0 0 n cierto 0 0 n 00n0n

La deduccin Q pmd(Inic, P ) n 0 0 n es trivialmente correcta. 5. Mantenimiento de la invarianza en cada iteracin


{P B }S {P } es correcta, o lo que es lo mismo, P B pmd(S, P ).

En este caso pmd(S, P ) pmd(r := r + x + 1; x := x + 1, P )


x+1 r +x+1 }r {{r = x =0 0 x n}x +1 +1 r +x+1 {r = x r + x + 1 = x =0 0 x + 1 n}r i=0 i 0 x + 1 n.

Luego la deduccin a demostrar queda

2.3.

VERIFICACIN FORMAL DE ALGORITMOS ITERATIVOS

23

x+1 r = x =0 0 x n x < n r + x + 1 = =0 0 x + 1 n,

sustituyendo en el consecuente r por su valor en el antecedente,


x+1 x r = x =0 0 x n x < n =0 + x +1 = =0 0 x +1 n,

introduciendo x + 1 en el sumatorio,
x+1 x+1 r = x =0 0 x n x < n =0 = =0 0 x + 1 n,

operando sucesivamente
r = x =0 0 x n x < n cierto 0 x + 1 n r = x =0 0 x n x < n 0 x + 1 n.

Esta deduccin es correcta, ya que, al cumplirse el operando subrayado es correcta la siguiente deduccin: 0 x n x < n 0 x + 1 n. 6. Cota inferior positiva (P B t 0). Primero, se realiza el clculo pospuesto de la funcin limitadora. Aplicando la heurstica indicada anteriormente se propone como funcin limitadora t n x. Luego en este caso:
r = x =0 0 x n x < n n x 0.

Es evidente que si x < n entonces n x 0, luego la deduccin es correcta. 7. Decrecimiento del nmero de iteraciones Para que {P B t = T }S {t < T } sea correcta, deber ser correcta
P B t = T pmd(S, t < T )
+1 r +x+1 pmd(S, t < T ) {{n x < T }x }r x

24

CAPTULO 2.

DISEO FORMAL DE ALGORITMOS ITERATIVOS

Luego, la deduccin queda


x+1 r +x+1 r = x }r , =0 0 x n x < n n x = T {{n x < T }x

operando sucesivamente en el consecuente


r +x+1 {n (x + 1) < T }r

n (x + 1) < T . n x 1 < T,

sustituyendo n x por su valor en el consecuente


T 1 < T , lo que es trivialmente Cierto, luego la deduccin es correcta.

Con lo que queda demostrada la correccin del algoritmo.

Captulo 3

Diseo formal de algoritmos recursivos


3.1 Lenguaje para algoritmos recursivos
La notacin que se va a utilizar para escribir algoritmos recursivos es la siguiente:

fun f (x : Tx ) dev (y : Ty ) caso Bt (x) triv (x) caso un


[] Bnt (x) c(x, f (s(x)))

{Q(x)}

{R(x, y )}

donde, adems de la precondicin, postcondicin y especicacin de la interfaz, los elementos del lenguaje algortmico recursivo que se utilizan son los siguientes:
Bt (x) es la condicin del caso trivial. triv (x) es la solucin del caso trivial. Bnt (x) es la condicin del caso no trivial. s(x) denota al conjunto de parmetros con los que se llama a la funcin

desde el propio algoritmo. A estos parmetros se les llamar parmetros sucesores de los actuales. c(x, f (s(x)) es la solucin del caso no trivial, siendo c 1 la funcin de combinacin de los parmetros actuales x con los resultados de la llamada a la funcin con los parmetros sucesores de los actuales f (s(x)) .
1 La funcin de combinacin que en la forma abstracta se ha escrito en notacin preja, se puede escribir igualmente en las notaciones postja e inja, esta ltima es la que se utilizar normalmente para las funciones artmeticas

25

26

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

[] es el separador de los casos. Adems, aunque no aparece explcitamente en la notacin, con (y ) se de-

notar a los resultados de llamar a la funcin con los parmetros sucesores.

Entendiendo que puede haber tantas estructuras de casos triviales y no triviales como necesite el algoritmo. Con esta notacin, el seudocdigo de la funcin factorial de un nmero n dado, se escribira de la forma siguiente:

fun f act(n : entero) dev (r : entero) caso n = 0 1 fcaso un


[] n > 0 n f act(n 1)
n =1

{Q n 0}

{R r =

donde se pueden identicar los distintos elementos de la notacin algortmica utilizada:


Q(x) n 0 f = f act xn Tx entero yr Ty entero Bt (x) n = 0 triv (x) 1 c s(x) n 1 f (s(x)) f act(n 1) c(x, f ((s(x)) n f act(n 1) R(x, y ) r = y r R(s(x), y ) r = y r
n1 =1 n =1

En el caso de una accin, es obvio que no tiene sentido hablar de funcin de combinacin El siguiente ejemplo muestra el seudocdigo del algoritmo recursivo para calcular el factorial de un nmero mediante una accin:

3.1.

LENGUAJE PARA ALGORITMOS RECURSIVOS

27

{Q n 0}

accion f actorial(n E : entero; r S : entero) caso n = 0 r := 1


[] n > 0 f actorial(n 1, r); r := n r

fcaso
{R r =

n =1

Adems el lenguaje permite utilizar variables locales mediante la siguiente clusula Sea q =expresiones 1 en expresin 2 : donde:
q es una lista de una o ms variables locales, separadas por comas. expresiones 1 es una lista de una o ms expresiones, separadas por comas, cuya evaluacin es la asignacin inicial a cada una de las variables q . expresin 2 es una expresin donde aparecen cada una de las variables locales q .

En el siguiente algoritmo se muestra la utilizacin de la clusula Sea:

fun suma(a : vector[1..n] de entero; i, j : entero) dev(s : entero) caso i > j a[i] [] i < j Sea m = (i + j ) div 2 en suma(a, i, m) + suma(a, m + 1, j ) fcaso un

3.1.1 Pasos para el diseo de un algoritmo recursivo


La secuencia de pasos del diseo de un programa recursivo, partiendo de la especicacin formal, se concreta en la siguiente: 1. Inmersin de la especicacin. Este paso se realizar necesariamente cuando la especicacin del problema no admite un diseo recursivo. Tambin, cuando an admitindolo, se quiera obtener la especicacin de otra funcin que sea ms eciente 2. Derivacin formal, que se subdivide en dos subpasos: (a) Anlisis por casos. (b) Composicin algortmica. 3. Vericacin formal de la correccin.

28

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

3.2 Inmersin de especicaciones


No todas las especicaciones permiten abordar directamente el diseo recursivo de una funcin. Cuando estemos en uno de estos casos tendremos que obtener la especicacin de una funcin ms general que si lo permitan. La tcnica utilizada para obtener la especicacin de la funcin ms general se conoce con inmersin de especicaciones. Una inmersin de la especicacin de una funcin f consiste especicar una funcin g ms general. La funcin g tendr, por tanto, ms parmetros que la f, por lo que, adems de tener que obtener los elementos de la terna {Q}S {R} de g, habr que calcular los valores de los nuevos parmetros que hagan que f sea un caso particular de g. A las funciones f y g se les llama, respectivamente, funcin sumergida y funcin inmersora. Para ilustrar estas ideas, se utilizar el ejemplo de la suma de los elementos de un vector, indexado entre 1 y n, siendo n una constante.

fun sumaV (v : vector[1..n] de entero) dev(s : entero)


{R s = n =1 v []}

{Q n 0}

No se tiene otra forma de partir el problema en problemas ms pequeos que la de partir el vector en vectores ms pequeos, pero eso signicara que cambiara el tipo del vector por lo que no se podra llamar recursivamente a sumaV. Pero si se piensa en una funcin con un parmetro adicional i,

fun iSumaV (v : vector[1..n] de entero; i : entero) dev(s : entero)


cuyo cometido sea calcular la suma de los elementos del vector que hay entre i y n, es decir, con una postcondicin R s = n =i v [], se ve que sumaV es un caso particular de iSumaV, aqul en el que i valga 1; es decir, sumaV (v ) = iSumaV (v, 1). Adems, iSumaV admite un diseo recursivo, ya que se sabe que, por las propiedades de la suma, iSumaV (v, i) = v [i] + iSumaV (v, i + 1). Formalmente, el problema consiste en, partiendo de una especicacin dada de f

fun f (x) dev (y ) {R(x, y )},


encontrar la de otra g ms general
{Q (x, w)} fun g (x, w) dev (y ) {R (x, w, y )},

{Q(x)}

3.2.

INMERSIN DE ESPECIFICACIONES

29

y adems calcular los valores wini , que hagan que f (x) = g (x, wini ), es decir, que f sea un caso particular de g . Vamos a ver dos tcnicas. La primera de ellas, inmersin no nal, lleva generalmente lleva al diseo de una funcin g recursiva no nal y la segunda, inmersin nal, siempre lleva al diseo de una funcin g recursiva nal. El punto de partida de ambas es la postocondicin R(x, y ). El convenio que se seguir para dar nombre a la funcin inmersora es preceder el nombre de la sumergida de una i cuando se haga una inmersin no nal y dos ies cuando se haga una inmersin nal.

3.2.1 Inmersin no nal


Tambin llamada inmersin por debilitamiento de la postcondicn, ya que la postcondicin de la funcin inmersora ser un debilitamiento de la sumergida. Los pasos a seguir son los siguientes: 1. En R se sustituyen constantes, o expresiones que solo dependan de x, por nuevos parmetros w obteniendo R (x, w, y ). La ecuacin de sustitucin ser w = (x), donde (x) denota a las expresiones sustituidas. 2. La precondicin Q se obtiene reforzando Q con las las condiciones de dominio2 que se necesiten poner a los nuevos parmetros. 3. Los valores iniciales, wini , vienen dados por la ecuacin de sustitucin. El siguiente ejemplo ilustra la aplicacin de esta tcnica a la especicacin de la funcin sumaV. 1. Se realiza la sustitucin i = 1, obteniendo R s = n =i v []. (Se podan haber hecho otras sustituciones, como i = n, i = n + 1 e, incluso, una tan disparatada como i = n + 5 2. La condicin de dominio de la nueva variable es que sta solo pueda tener valores dentro del rango de indices del vector. Por tanto, Q n 0 1 i n. 3. El valor inicial de i, viene dado por la ecuacin de sustitucin, es decir 1. La especicacin resultante sera:

fun iSumaV (v : vector[1..n] de entero; i : entero) dev(s : entero) {R s = n =i v []}.


Siendo la llamada inicial sumaV (v ) = iSumaV (v, 1)
2 En el anlisis por casos puede que haya que modicar ligeramente las condiciones de dominio de los nuevos parmetros para poder obtener una solucin para un caso trivial

{Q n 0 1 i n}

30

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

3.2.2 Inmersin nal


Tambin llamada inmersin por reforzamiento de la precondicn, debido a que la precondicin de la funcin inmersora es la de la sumergida en conjuncin con un debilitamiento de la postcondicin de la sumergida. La postcondicin de la inmersora es la misma que la de la sumergida. Esta tcnica da, por aadidura, la condicin y la solucin de un caso trivial. Una particularidad de la aplicacin de esta tcnica es que la postcondicin que se obtiene es constante. Se dice que una postcondicin es constante cuando su expresin es la misma tanto para los parmetros actuales como para sus sucesores, es decir, en la postcondicin solo aparecen parmetros de entrada que permanecen constantes. Toda funcin con postcondicin constante es recursiva nal, pero no toda recursiva nal es de postcondicin constante. Las funciones recursivas con postcondicin constante presentan ventajas para transformar su algoritmo en uno iterativo. Los pasos a seguir son los siguientes:
Se renombran en la postcondicin los parmetros de salida y por nuevos parmetros de entrada w1 , obteniendo R(x, w1 ). Los parmetros w1 sern

la solucin del caso trivial. Si R ya est en forma conjuntiva, es decir R R1 (x, w1 ) R2 (x, w1 ):

 Elegir, entre R1 y R2 , aqul predicado en el que sea ms fcil dar valores a los parmetros w1 que hagan que se cumpla el predicado. Ese predicado reforzar la precondicin de la sumergida. El otro ser la condicin del caso trivial.
Si R no est o no se puede poner en forma conjuntiva:

 Obtener R (x, w1 , w2 ), realizando una sustitucin w2 = (x, w1 ), de forma anloga a como se haca en el mtodo de inmersin no nal.  R reforzar la precondicin de la sumergida. La ecuacin de sustitucin w2 = (x, w1 ) ser la condicin del caso trivial.
La precondicin ser el reforzamiento obtenido, junto a las condiciones de dominio que sea necesario poner a los nuevos parmetros w Los valores iniciales wini , que hacen que f (x) = g (x, wini ), sern aquellos

que hagan que se cumpla la precondicin de la nueva funcin.

Se va a ilustrar la aplicacin de esta tcnica con el mismo ejemplo utilizado en la inmersin nal.
Se renombra enR s por ss, obteniendo R ss = n =1 v []. Como R no est en forma conjuntiva, se realiza la sustitucin i = n, obteniendo R ss = i =1 v []. La precondicicin de iiSumaV ser n 0 ss = i =1 v [] 1 i n

3.3.

ANLISIS POR CASOS Y COMPOSICIN ALGORTMICA

31

Los valores iniciales ss = 0 e i = 0 cumpliran la precondicin si se admitiese que el dominio de valores de i, incluya el valor 0, por lo que se

modica la precondicin en ese sentido.

La especicacin resultante sera:


{Q n 0 ss = i =1 v [] 0 i n} fun iiSumaV (v : vector[1..n] de entero; ss, i : entero) dev(s : entero) {R s = n =1 v []}.

Siendo la llamada inicial sumaV (v ) = iiSumaV (v, 0, 0). Adems se tiene ya un caso con condicin i = n y solucin trivial ss

3.3 Anlisis por casos y composicin algortmica


Una vez se tiene una especicacin que admite el diseo de un algoritmo recursivo, el siguiente paso es el de derivar el algoritmo. Este paso se divide, a su vez, en dos subpasos: l anlisis por casos y la composicin algortmica.

3.3.1 Anlisis por casos


Este paso consiste en identicar todos los casos posibles y su correspondiente solucin. Una estrategia, que se suele seguir, es la de identicar un caso con una solucin trivial y buscar una solucin para otro caso que abarque el resto de los estados previstos por la precondicin. Si se encuentra una solucin no trivial se habr acabado este paso 3 . En el caso de que no se encuentre, se tratar de encontrar una solucin, trivial o no trivial, para un subconjunto de los estados del caso y otra para el resto de los estados. Este proceso se repetir hasta que no haya ningn estado, previsto por la precondicin, sin su correspondiente solucin. De esta forma se consigue un conjunto de casos mutuamente excluyentes y que, entre todos, abarcan todos los estados previstos por la precondicin. Aunque no es necesario, es aconsejable ir plasmando la condicin y la solucin de cada caso en una tabla de doble entrada. Una plantilla de esa tabla podra ser la siguiente:

Condicin Condicin 1 Condicin 2 . . . Condicin n

Solucin Solucin 1 Solucin 2 . . . Solucin n

3 obviamente, si se encontrase una solucin trivial, tambin se habra acabado, pero el algoritmo obtenido no sera recursivo

32

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

Habr veces que la tabla tendr que ser ms compleja para reejar situaciones de condiciones encadenadas. La siguiente podra la tabla de una situacin con dos casos, uno de ellos con dos subcasos.

Condiciones Condicin 1 Condicin 2 Condicin 2.1 Condicin 2.2

Solucin Solucin 1 Solucin 2.1 Solucin 2.2

Obtencin de casos triviales Una forma bsica de conseguir un caso trivial es ver qu valores deben tener alguno de los parmetros de entrada para anular el dominio de algn cuanticador que aparezca en la postcondicin, lo que, automticamente, llevar a la solucin trivial del caso. Tomando como ejemplo la especicacin de la funcin iSumaV (resultado del ejemplo de inmersin no nal), se puede ver que hay un caso trivial cuando i = n + 1, cuya solucin, al anularse el rango del , ser el elemento neutro de la suma, es decir 0. Como el valor n + 1 no pertenece al dominio de i que se deni en el paso 2, por conveniencia, habr que modicar el dominio para que i pueda valer n + 1.
Si se estuviese haciendo el anlisis por casos de la especicacin de la funcin iiSumaV (resultado del ejemplo de inmersin nal), se partira de que ya se tiene un caso trivial i = n con solucin ss.

Obtencin de casos no triviales La obtencin de una solucin no trivial consiste en obtener la ley de recurrencia, es decir la funcin de combinacin y los parmetros sucesores. Cuando se haga el planteamiento para calcular la ley de recurrencia, cada uno de los parmetros sucesores se podr: expresar que permanezca constante, proponer una expresin (si se tienen argumentos para hacer una propuesta) o expresarlo como una incgnita. Bsicamente, habr dos situaciones:
Cuando en la postcondicin aparezcan parmetros de entrada que puedan

variarse. Una buena estrategia es comparar el predicado de la postcondicin con el de la misma, pero cambiando en ella los parmetros de entrada por sus parmetros sucesores y los parmetros de salida por nuevos parmetros de salida, y ver si se pueden poner los parmetros de salida en funcin de los parmetros actuales y los nuevos de salida. Formalmente sera plantear R(x, y ), R(s(x), y ) y ver si se puede conseguir una funcin c tal que y = c(x, y ) Siguiendo con el ejemplo de la funcin iSumaV , la condicin del caso no trivial ser i = n + 1, pero, teniendo en cuenta las condiciones de dominio, se podr dejar como i < n + 1. Dado que, i empieza valiendo 1 y termina

3.3.

ANLISIS POR CASOS Y COMPOSICIN ALGORTMICA

33

valiendo n + 1, parece lgico proponer como sucesor de i a la expresin i +1. El sucesor del parmetro a, no puede ser otro que l mismo. Al nuevo resultado se le llamar s . Comparando la postcondicin s = n =i v [] con la misma para los parmetros sucesores y la nueva salida s = n =i+1 v [], se puede deducir que s = s + v [i]. Dado que se ha encontrado la ley de recurrencia para el caso i < n +1 se da por terminado el anlisis por casos.
Cuando en la postcondicn slo aparezcan parmetros de entrada que no

puedan modicarse.

Esa es una situacin con postcondicin constante, por tanto, no habr funcin de combinacin y lo nico que habr que calcular son las expresiones de los parmetros sucesores, de los de entrada que no aparezcan en la postcondicin. Para ello se utilizar la propiedad de que la precondicin se debe cumplir tanto en la llamada externa como en las internas. Formalmente eso signica que deber ser correcta la deduccin
Q(x) Bnt (x) Q(s(x))

En el ejemplo de la funcin iiSumaV , se plantea un caso no trivial cuya condicin, teniendo en cuenta las condiciones de dominio de i, ser i < n. Como la postcondicin es constante, ya que n es el lmite superior del ndice del vector, se plantea la siguiente deduccin:
n 0 ss = i =1 v [] 0 i n i < n
+1 n 0 suc(ss) = i =1 v [] 0 i + 1 n

(Se ha propuesto que el sucesor de i sea i + 1, ya que su valor inicial es 0 y su valor nal es n; el de ss se ha dejado como incgnita y el de n debe ser l mismo). Si se desarrolla el del consecuente, ste queda por su valor en el antecedente, el consecuente queda del consecuente.
n 0 suc(ss) = i =1 v [] + v [i + 1] 0 i + 1 n, sustituyendo el

n 0 suc(ss) = ss + v [i + 1] 0 i + 1 n, que directamente da la expresin de suc(ss) para que se evale a cierto el segundo conjuntando

Se deja como ejercicio para el lector la demostracin de que los otros dos conjuntandos del consecuente tambin se evalan a cierto. La tabla resultante para el anlisis por casos de la funcin iSumaV sera la siguiente

Condicin
i=n+1 i<n+1

Solucin 0
v [i] + iSumaV (v, i + 1)

La de la funcin iiSumaV sera la siguiente:

34

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

Condicin
i=n i<n

Solucin
ss iiSumaV (v, ss + v [i + 1], i + 1)

Aunque, una vez hecha la composicin algortmica, habr que vericar formalmente el algoritmo derivado, hay tres comprobaciones importantes que es conveniente realizar informalmente en este paso:
Comprobar informalmente que los parmetros sucesores en las soluciones

no triviales llevan de forma inequvoca a un caso trivial. por la precondicin.

Comprobar que entre todos los casos cubren todos los estados previstos Comprobar que los casos sean mutuamente excluyentes.

Siguiendo con el ejemplo de la funcin iSumaV , analizando la tabla se ve que:


Sumando 1 a i, por muy grande que sea el n, se llegar al caso en que i=n+1 Entre el caso i = n + 1 y el i < n + 1 cubren todos los estados previstos por la precondicin n 0 1 i n + 1. Los casos i = n + 1 y el i < n + 1 son mutuamente excluyentes.

Se deja como ejercicio para el lector la realizacin de las comprobaciones para la tabla de la funcin iiSumaV .

3.3.2 Composicin algortmica


El paso de composicin algortmica consiste en trasladar la tabla de anlisis por casos al lenguaje recursivo utilizado. Llevando la tabla de anlisis por casos de la funcin iSumaV al lenguaje recursivo, el algoritmo resultante ser el siguiente:

fun iSumaV (v : vector[1..n] de entero; i : entero) dev(s : entero) caso i = n + 1 0 fcaso un
[] i < n + 1 v [i] + iSumaV (v, i + 1)

{Q n 0 1 i n }

{R s = n =i v []}.

Y el algoritmo resultante correspondiente a la tabla de la funcin iiSumaV


{Q n 0 ss = i =1 v [] 0 i n}

3.4.

VERIFICACIN FORMAL

35

fun iiSumaV (v : vector[1..n] de entero; ss, i : entero) dev(s : entero) caso i = n ss fcaso un
[] i < n iiSumaV (v, ss + v [i + 1], i + 1)

{R s = n =1 v []}.

Declaracin de variables locales En algunas situaciones ser conveniente introducir declaraciones de variables locales para evitar clculos repetidos. Tomando como ejemplo la siguiente tabla, que resume el anlisis por casos de una funcin potEf cte para calcular la potencia n -sima de un nmero a, de una forma ms eciente que la bsica Condiciones
n=0 n>0 n mod 2 = 0 n mod 2 = 1

Solucin 1
(an div 2 ) (an div 2 ) a (an div 2 ) (an div 2 )

La expresin del algoritmo recursivo sera la siguiente:

caso n = 0 1 [] n > 0 caso n mod 2 = 0 potEf cte(a, n div 2)potEf cte(a, n div 2) [] n mod 2 = 1 apotEf cte(a, n div 2)potEf cte(a, n div 2) fcaso fcaso
Donde se ve que se puede ahorrar el llamar dos veces a la funcin y, adems, calcular en cada llamada el resultado de la expresin n div 2, si se hace una declaracin de una variable local p que recoja el resultado de potEf cte(a, n div 2), quedando la siguiente expresin del algoritmo:

caso n = 0 1 [] n > 0 sea p = potEf cte(a, n div 2) en caso n mod 2 = 0 p p [] n mod 2 = 1 a p p fcaso fcaso

3.4 Vericacin formal


3.4.1 Base terica: El principio de induccin noetheriana
En este apartado se va a repasar la base terica sobre la que se apoya la vericacin de la correccin de una funcin recursiva.

36

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

La tcnica bien conocida de demostracin basada en el principio de induccin sobre los nmeros naturales se puede expresar mediante la siguiente regla de inferencia:
P (0), N.(P () P ( + 1)) N.P ()

Es decir para demostrar la propiedad P (n) basta con demostrar la propiedad para n = 0, P (0) (base de la induccin), y que el cumplimiento de P para cualquier nmero natural implica el cumplimiento para el nmero siguiente + 1 (recurrencia). La regla anterior se puede generalizar a la siguiente:
P (0), N.(( [0, 1].P ( )) P ()) N.P ())

Dado que P (0) est incluido en el predicado N.(( [0, 1].P ( )) P ()), la regla se puede simplicar a la la siguiente:
N.( [0, 1].P ( )) P ()) N.P ()

El principio de induccin sobre el conjunto de los nmeros naturales se puede generalizar sobre otras estructuras de datos que sean prerdenes bien fundados (pbf ). Si se tiene un conjunto D sobre el que se dene una relacin binaria , se dice que (D, ) es un preorden si los elementos de D cumplen las propiedades reexiva ( D. ) y transitiva (, , D.( ) ( ) ( )). Los siguientes son ejemplos de preordenes:
Los nmeros naturales con la relacin (N, ). Los nmeros enteros con la relacin (Z, ). El conjunto de las cadenas de caracteres con la relacin de orden alfabtico (orden_alf abetico ) denida como c1 orden_alf abetico c2 si y solo si la cadena c1 es igual o precede alfabticamente a la cadena c2

Se dice que en un preorden (D, ) x precede estrictamente a y (x y ), cuando se cumple que (x y ) (y x). Una sucesin de elementos x1 , x2 , x3 , . . . de un preorden (D, ) es estrictamente decreciente, si para todo par xi , xi+1 de elementos consecutivos de la sucesin se tiene que xi+1 xi . Un preorden (D, ) es noetheriano si no existen sucesiones innitas estrictamente decrecientes en D. Dado un preorden (D, ), se dice que x D es un minimal si no hay otro elemento en D que preceda estrictamente a x. Un preorden (D, ) es un pbf si en D hay al menos un minimal. Todo pbf es noetheriano y viceversa.

3.4.

VERIFICACIN FORMAL

37

(Z, ). Sin embargo, los nmeros enteros con la relacin (Z, ) no es un

Un pbf bien conocido es el conjunto de los nmeros naturales con la relacin

pbf, ya que todo nmero entero tiene otro que le precede estrictamente. S es un pbf el conjunto de los enteros en el intervalo [0, ] con la relacin . El principio de induccin es vlido en un pbf (D, ), es decir, si P es una propiedad sobre los elementos de D, se cumple que:
D.( D. < P ( )) P () D.P ()

Cuando se est analizando un algoritmo no es inmediato encontrar un pbf para poder aplicar el principio de induccin. Sin embargo, s se podr denir induciendo un pbf sobre un conjunto D a partir de otro preorden (D, ) conocido, como puede ser el preorden (N, ). Sea D un conjunto cualquiera, (D , c ) un pbf y f una funcin de D en D (f : D D ). Entonces (D, c ) ser un pbf si se se dene de la siguiente forma:
x, y D.(x c y f (x) c f (y ))

A continuacin se presentan algunos ejemplos de denicin de un pbf sobre el conjunto N N , deniendo diversas funciones f : N N N :
(x , y 1 (x, y ) x x) (x , y 2 (x, y ) y y ) (x , y 3 (x, y ) (x + y ) (x + y ))

En cambio (x , y 4 (x, y ) (x y ) (x y )) no es un pbf, ya que la resta de dos naturales puede que no sea otro natural. Otro ejemplo es el siguiente: siendo Csec el conjunto de las secuencias de datos de un determinado tipo de dato y s1 , s2 dos secuencias cualesquiera de dicho conjunto, (Csec , lsec ) es un pbf, deniendo la relacin binaria lsec de la forma:
s1 , s2 Csec .(s1 lsec s2 longitud(s1 ) longitud(s2 )

Las funciones de cota que se utilizan para demostrar la terminacin tanto de bucles como de secuencias de llamadas recursivas son una aplicacin de esta forma de inducir pbf s. Al igual que en los algoritmos iterativos, para vericar la correccin total de un algoritmo recursivo habr que demostrar que:
Es correcto parcialmente. Termina.

38

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

3.4.2 Vericacin de la correccin parcial


Las propiedades que debe cumplir un algoritmo recursivo para que se considere parcialmente correcto son las siguientes: 1. Completitud de las alternativas La disyuncin de todos los casos es deducible de la precondicin.
Q(x) Bt (x) Bnt (x))

Ntese que si solo hay dos casos Bnt (x) Bt (x) 2. Satisfaccin de la precondicin en la llamada interna Una solucin no trivial realiza una llamada al algoritmo con unos parmetros que cumplen la precondicin.
Q(x) Bnt (x) Q(s(x))

(En este punto se deben realizar tantas demostraciones como casos no triviales haya) 3. Hiptesis de la induccin Una solucin trivial cumple la postcondicin.
Q(x) Bt (x) R(x, triv (x))

(En este punto se deben realizar tantas demostraciones como casos triviales haya) 4. Paso de induccin Una solucin no trivial cumple la postcondicin, supuesto conocida la solucin a la llamada recursiva.
Q(x) Bnt (x) R(s(x), y ) R(x, c(x, y ))

(En este punto se deben realizar tantas demostraciones como casos no triviales haya) Con esto quedara demostrado que el algoritmo es correcto parcialmente.

Vericacin de la terminacin del algoritmo Para vericar que un algoritmo recursivo no pueda entrar en una sucesin innita de llamadas recursivas, se tendr que encontrar una funcin cota t que cumpla unas propiedades similares a las exigidas para algoritmos iterativos. Es decir:
Se debe mantener positiva en todas y cada una de las llamadas al algoritmo

recursivo. Cada vez que se hace una llamada recursiva el valor de la funcin decrece estrictamente. La heurstica para encontrarla es la misma que la utilizada para algoritmos iterativos. La funcin cota t deber cumplir que:

3.4.

VERIFICACIN FORMAL

39

1. Tiene estructura de preorden bien fundado. Se mantiene 0


Q(x) t(x) 0

2. Decrece estrictamente en cada llamada interna (Decrecimiento del tamao del problema).
Q(x) Bnt (x) t(x) > t(s(x))

Lo que hace un total de 6 propiedades a demostrar. A continuacin se ilustra la demostracin de estas seis propiedades con el ejemplo de la funcin factorial de la seccin ??. En cada unos de los puntos se van identicando las expresiones necesarias an no identicadas. La demostracin de la correccin de una deduccin, se puede hacer de tres formas distintas:
Identicar predicados en el antecedente y en el consecuente donde se vea

claramente que el antecedente es ms fuerte que el consecuente. Sustituir expresiones del antecedente en el consecuente y evaluar el consecuente como cierto, que al ser el predicado ms dbil har que la deduccin sea correcta. Partiendo de todo o parte del antecedente, realizar deducciones lgicas hasta llegar a una que sea el consecuente
Q(x) Bt (x) Bnt (x)) Q(x) n 0 Bt (x) n = 0 Bnt (x)) n > 0

1. Completitud de las alternativas

Luego la deduccin a demostrar su correccin es la siguiente:


n0
? n

=0 n>0

Como en ambos lados aparece el mismo predicado, se puede decir que el antecedente es ms fuerte que el consecuente. Por tanto, esta deduccin es correcta. 2. Satisfaccin de la precondicin en la llamada interna
Q(x) Bnt (x) Q(s(x))

40

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

s(x) n 1 Q(s(x)) (n 1) 0
? n 0 n > 0 (n 1) 0

Se tiene que, partiendo del predicado subrayado,


n > 0 n 1 n 1 0 son deducciones correctas. Luego la deduc-

cin es correcta por ser el predicado del antecedente ms fuerte que el del consecuente. 3. Hiptesis de la induccin
Q(x) Bt (x) R(x, triv (x)) triv (x) 1 R(x, triv (x)) 1 =
? n 0 n = 0 1 = n =1

, sustituyendo en el consecuente n por su

valor en el antecedente:
1=
0 =1

n =1

1 = 1 cierto. La deduccin es correcta por ser Cierto el predicado

ms dbil.

4. Paso de induccin
Q(x) Bnt (x) R(s(x), y ) R(x, c(x, y )) y r R(s(x), y ) r = c c(x, y ) n r R(x, c(x, y )) n r =
n =1 n1 =1

3.5.

INMERSIN DE ALGORITMOS

41
n

n1

n 0n > 0r =
Q(x) Bnt (x) =1

? nr = =1 R(x,c(x,y ))

R(s(x),y )

sustituyendo en el consecuente r por su valor en el antecedente


n
n1 =1

n =1

introduciendo el trmino (n)-simo en el producto

n =1

n =1

Cierto. La deduccin es correcta por ser Cierto el predicado ms dbil. 5. Estructura de preorden bien fundado Se propone como funcin cota t n, con lo que: Q(x) t(x) 0
? n 0 n 0 (trivial)

6. Decrecimiento del tamao del problema


Q(x) Bnt (x) t(x) > t(s(x))
? n 0 n > 0 n > n 1 (trivial)

Con lo que queda vericada formalmente la correccin total del algoritmo.

3.5 Inmersin de algoritmos


En este apartado se van a presentar una serie de tcnicas que permiten pasar de un algoritmo de una funcin recursiva al de otra ms general. Estas tcnicas se aplican cuando se quiere mejorar la eciencia de un algoritmo. Por eso a este tipo de inmersin se le llama tambin inmersin por razones de eciencia. A continuacin se van a ver tres de estas tcnicas: Desplegado y plegado, inmersin de parmetros de entrada e inmersin de parmetros de entradas e inmersin de parmetros de salida.

3.5.1 Desplegado y plegado


Esta tcnica se puede aplicar solo a algoritmos recursivos lineales no nales en los que la funcin de combinacin de la solucin no trivial cumpla las propiedades de:

42

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

tener elemento neutro, ser asociativa

La tcnica tiene tres pasos: 1. Generalizacin. Se dene la funcin inmersora de f (x) de la siguiente manera: g (x, w) = c(f (x), w), siendo c la funcin de combinacin de la solucin no trivial de f . Es evidente que, si c tiene elemento neutro w0 , g (x, w0 ) = c(f (x), w0 ) = f (x). Por tanto, w0 sern los valores iniciales de los nuevos parmetros w que hacen que la funcin inmersora simule a la sumergida. 2. Desplegado. Se despliega el algoritmo de f (x) en la denicin de g (x, w). Es decir, g (x, w) = c(f (x), w) = c( caso Bt (x) triv (x)
[] Bnt (x) c(f (s(x), x))

fcaso, w) = caso Bt (x) c(triv (x), w)


[] Bnt (x) c(c(f (s(x), x)), w)

fcaso Teniendo en cuenta, que c es asociativa = caso Bt (x) c(triv (x), w)


[] Bnt (x) c(f (s(x)), c(x, w))

fcaso
3. Plegado. Se pliega el algoritmo de acuerdo a la denicin de g (x, w) = caso Bt (x) c(triv (x), w)
[] Bnt (x) g (s(x), c(x, w))

fcaso
La precondicin de la funcin inmersora ser la de la sumergida en conjuncin con las condiciones de dominio de los nuevos parmetros, es decir Q (x, w) Q(x Dom(w). En cuanto a su postcondicin, sta viene dada por la denicin de la funcin, es decir, R (x, w, y ) y = c(f (x), w) Se va a ilustrar la aplicacin de sta tcnica al algoritmo de la funcin factorial

3.5.

INMERSIN DE ALGORITMOS

43

1. Generalizacin. Se dene iiF actorial(n, w) = w F actorial(n), como 1 es el elemento neutro de la multiplicacin, iiF actorial(n, 1) = F actorial(n). Es decir 1 ser el valor inicial de w que hace iiF actorial(n, w) simule a
F actorial(n)

2. Desplegado. Se despliega el algoritmo de F actorial en la denicin de iiF actorial. Es decir, iiF actorial(n, w) = w F actorial(n) = w (caso n = 0 1
[] n > 0 n F actorial(n 1)

fcaso)
= caso n = 0 w 1
[] n > 0 w (n F actorial(n 1))

fcaso Teniendo en cuenta, que es asociativa = caso n = 0 w


[] n > 0 (w n) F actorial(n 1))

fcaso
3. Plegado. Se pliega el algoritmo de acuerdo a la denicin de iiF actorial(n, w)) = caso n = 0 w
[] n > 0 iiF actorial(n 1), w n)

fcaso
La postcondicin R w F actorial(n), que no tiene la caracterstica de postcondicin constante. La precondicin de la funcin ser la de F actorial, ya que no tenemos forma de imponer condiciones de dominio a w. Aunque se puede ver que en w se va acumulando el producto de los enteros entre el valor de n con el que se llame externamente a la funcin y el valor actual de n + 1, no hay forma de expresar esto, porque el algoritmo no recuerda el valor n inicial.

44

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

Con todo esto el algoritmo resultante ser

fun iiF actorial(n, w : entero) dev (r : entero) caso n = 0 w fcaso un


[] n > 0 iiF actorial(n 1, n w)
n =1

{Q n 0}

{R r = w

Si se aplicase sta tcnica al algoritmo recursivo no nal de iSumaV (n, i) para obtener iiSuma2 V (v, ss, i) (ejercicio que se deja para el lector) si se llamase ss al nuevo parmetro de inmersin, la postcondicin resultante sera
R r = ss + n =i v [] iiSuma2 V [v, 0, 1], podramos dejarla como R r = n =1 v [], y adems como
n r = ss + n =i v [] = =1 v [], si despejamos ss i1 n ss = n =1 v [] =i v [] = =1 v []. Condicin que imponemos en la

Pero, como tendramos las siguientes igualdades SumaV [v ] = iSumaV [v, 1] =

precondicin, por lo que esta quedar

Cuando los algoritmos no son tan sencillos como el del ejemplo, ser de bastante ayuda, para la obtencin de la denicin de la funcin inmersora, construir el rbol sintctico de la solucin no trivial y realizar ciertas operaciones sobre. Vamos a ilustrar la obtencin de la denicin de iiF actorial con la ayuda del arbol sintctico de F actorial. 1. Se construye el rbol sintctico de la solucin no trivial
/ * \

Q n 0 1 i n + 1 ss = n =i+1 v []

/ n

\ Factorial | n - 1

2. Se poda el rbol de la siguiente manera:


se deja una sola rama en los subrboles laterales al camino que va

desde la funcin de combinacin al nodo con el nombre de la funcin

3.5.

INMERSIN DE ALGORITMOS

45

por debajo del nombre de la funcin se dejan tantas ramas como

parmetros tenga la funcin

El resultado sera
/ * \

\ Factorial |

3. Se rellenan las hojas del rbol con:


parmetros de inmersin en las ramas laterales parmetros originales en las que nacen del nombre de la funcin

El rbol resultante sera


/ * \

\ Factorial | n

4. Escribir la denicin de la nueva funcin leyendo el rbol resultante. En este caso, iiF actorial(n, w) = w F actorial(n) Habr situaciones donde haya ms de una solucin no trivial. En ese caso habr que operar sobre el algoritmo para conseguir que haya un solo caso y que el nombre de la funcin solo aparezca una vez. Para ello, podemos ayudarnos de funciones auxiliares que no habr que implementar. Vamos a ilustrar estas situaciones con el algoritmo de la funcin potEf cte escrito al nal de la seccin 3.3. Como el nombre de la funcin no aparece explcitamente en ninguna de las dos ramas nos quedamos con la versin que no tiene declarada p , que reescribimos como sigue:
potEf cte(a, n) = caso n = 0 1 [] n > 0 caso n mod 2 = 0 [potEf cte(a, n div 2)]2 [] n mod 2 = 1 a [potEf cte(a, n div 2)]2

fcaso

fcaso

Si nos jamos vemos que la nica diferencia entre las dos soluciones no triviales es que la segunda es igual a la primera multiplicada por a, por lo que podemos pensar en una funcin auxiliar cond(a, n) =

46

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

caso n mod 2 = 0 1 [] n mod 2 = 1 a fcaso


Con lo que reescribimos el algoritmo de la siguiente manera:
potEf cte(a, n) = caso n = 0 1 [] n > 0 cond(a, n) [potEf cte(a, n div 2)]2

fcaso que ya est en la forma que nos interesa. A continuacin se ilustra de forma resumida la denicin de iiP otEf cte
1. Construccin del rbol
*

/ cond / \ / \ a n

/ \ / \ potEfcte 2 / \ / \ a n div 2

\ ^

2. Poda
*

/ \ / \ potEfcte / \ / \

\ ^

3. Relleno

3.5.

INMERSIN DE ALGORITMOS

47

/ \ / \ potEfcte w / \ / \ a n

\ ^

4. La denicin de la funcin que sale de la lectura del rbol sera: establecer la siguiente igualdad
iiP otEf cte(a, n, u, w) = u [potEf cte(a, n)]w , donde se ve que se puede

iiP otEf cte(a, n, 1, 1) = potEf cte(a, n).

En este caso, iiF actorial(n, w) = w F actorial(n) Se deja como ejercicio para el lector la aplicacin del resto de la tcnica, cuya solucin es la siguiente caso n = 0 u [] n > 0 caso n mod 2 = 0 iipotEf cte(a, n div 2, u, 2 w) [] n mod 2 = 1 iipotEf cte(a, n div 2, u aw , 2 w) fcaso fcaso

Obtencin de una postcondicin constante


Los algoritmos recursivos nales se pueden transformar en iterativos de un solo bucle. Si, adems, su postcondicin es constante la derivacin del invariante del bucle es relativamente sencilla, ya que ser un debilitamiento de la postcondicin. A continuacin se presenta un mtodo para obtener un algoritmo recursivo nal con postcondicin constante a partir de otro recursivo nal sin la caracterstica de postcondicin constante.
Se duplicarn aquellos parmetros de entrada que tengan sucesores dis-

tintos a ellos mismos. Estos nuevos parmetros permanecern constantes a lo largo de todas las llamadas internas. con duplicado por su duplicado.

La postcondicin ser el resultado de sustituir en la antigua los parmetros

48

CAPTULO 3.

DISEO FORMAL DE ALGORITMOS RECURSIVOS

Se reforzar la precondicin con un aserto que diga que la postcondi-

cin sobre los parmetros que varan implica la pstcondicin sobre los parmetros duplicados

Aplicando el mtodo al algoritmo de iiF actorial, resultante de aplicar la tcnica de desplegado y plegado al de F actorial:
Como los dos parmetros, n y w, varan, incorporamos dos nuevos parmetros N y W para recibir los valores iniciales de n y w, respectivamente. La postcondicin ser, por tanto, r = N ! W . El aserto para reforzar la precondicin ser r = n! w r = N ! W , es decir, n! w = N ! W

Como sabemos que el valor inicial de w y, por tanto, el de W es 1, podemos prescindir del duplicado. El algoritmo resultante ser el siguiente:

fun iiF actorial2 (n, w, N : entero) dev (r : entero) caso n = 0 w fcaso un
[] n > 0 iiF actorial(n 1, n w)

{Q n 0 n! w = N !}

Siendo la llamada inicial iiF actorial2 (n, 1, n).

{R r = N !}

Vous aimerez peut-être aussi