Вы находитесь на странице: 1из 24

Especificacion y correccion de algoritmos

Monica Mara Lozano Romero


Politecnico Grancolombiano
2010
Indice general

1. Especificacion y correcion de algoritmos 1


1.1. Introduccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2. Especificacion de algoritmos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.3. Correcion de asignacion y condicionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3.1. Correcion de asignaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3.2. Correccion de condicionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.4. Correccion de ciclos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

i
Especificacion y correccion de algoritmos

ii
Captulo 1: Especificacion y correcion de algoritmos

En este captulo se introduce los conceptos basicos de la especificacion y correccion de algoritmos, cuya
base primordial es el calculo de predicados, visto en el curso previo a este, y las propiedades de induccion
de los naturales explicadas en el captulo anterior.

Se introducen dos conceptos primordiales como lo es la precondicion y poscondicion de un programa,


ya que permite definir las condiciones iniciales y finales que se deben satisfacer para que dicho algorimo
inicie y termine de manera correcta (haga lo que tiene que hacer a partir del punto de donde debe iniciar
), de tal manera que oriente su diseno e implementacion. Adicionalmente, se introduce la manera correcta
de plantear y construir tres elementos basicos en programacion: las asignaciones, los condicionales y los
ciclos. Dado que estos son las bases para la elaboracion de programas correctos que solucionan problemas
de la vida real.
El estudiante al final del captulo podra utilizar su contenido y el conocimiento en metodos de demos-
tracion adquirido en el curso anterior para disenar, demostrar y especificar algoritmos correctos de acuerdo
al problema de programacion planteado utilizando los resultados mas relevantes expuestos en este captulo.
El contenido de este captulo se baso en [1].

Seccion 1.1: Introduccion

Cuando se esta disenando un algoritmo siempre se deben tener en cuenta tres cosas: primero que
condiciones se necesitan para que inicie el algoritmo de manera correcta, segundo que esas condiciones
se mantengan mientras el algoritmo se esta ejecutando, y por ultimo el algoritmo tiene un fin para el
cual fue disenado, de esa manera cuando el algoritmo haya terminado hay que verificar que realmente las
condiciones de aceptacion de su ejecucion se cumplen.

Un algoritmo es simplemente un conjunto de pasos que al ejecutarse cambia un conjunto de estados


iniciales a un conjunto de estados finales. Ese algoritmo tiene asignaciones, condiciones y ciclos, que deben
ejecutarse uno tras otro de manera correcta. Por esa razon en la especificacion y correccion de algoritmos
no solo nos preocupamos por entender bien el problema (precondicion, poscondicion y todos su posibles
estados cuando esta en ejecucion) sino en disenarlo de manera correcta, es decir que las asignaciones, condi-
ciones y ciclos que all aparezcan esten correctos en terminos del mismo problema que se este solucionando,
es decir, que haga lo que se pretendio que tena que hacer.

En este captulo vamos a ir introduciendo de manera progresiva como especificar un programa o


algoritmo, como hacer la correcion de asignaciones, condicionales y ciclos. De tal manera que cuando se
tenga un algoritmo completo se pueda verificar su correccion con respecto a su especificacion.

Seccion 1.2: Especificacion de algoritmos

Cuando nos plantean un problema de programacion para el cual hay que proponer una solucion, lo
primero que se tiene que hacer es entender que requiere el problema. Dicho de otra manera, se tiene que

1
Especificacion y correccion de algoritmos Especificacion de algoritmos

especificar el programa que nos estan solicitando solucionar, para poder especificar o entender un problema
se deben tener en cuenta dos elementos:

a) Precondicion: Las condiciones iniciales que se deben cumplir antes de iniciar su ejecucion.

b) Poscondicion: Las condiciones finales que debe cumplir el el programa, de tal manera que coincidan
con lo que el programa tiene hacer.

Entre la precondicion y la poscondicion esta el algoritmo o programa que soluciona el problema. Con estos
tres elementos se especifica un programa, esta especificacion se representa como una Tripla de Hoare:

{Q} S {R}

Esa tripla Hoare lo que realmente significa es que S se ejecuta siempre que Q se cumpla (o sea verdadera) y
S termina haciendo que R sea verdadera, o dicho de otra manera Q es la precondicion, R es la poscondicion
y S el programa. Cabe resaltar que tanto la precondicion como la poscondicion se escriben en el lenguaje
de calculo de predicados.

El siguiente ejemplo ilustra como se debe especificar un algoritmo, de tal manera que solo se pueda
interpretar de una manera, es decir, que no de pie a ningun tipo de ambiguedad:

Ejemplo 1.1
Suponga que se quiere especificar el programa que dado un arreglo b[n] encontrar el ndice i (con i en el
rango del tamano del arreglo b) donde se encuentra un valor x dado, la siguiente tripla de Hoare especificara
el programa de manera precisa:

{x b[0 . . . n 1]} i =? {0 i < n x = b[i]}

Note que como precondicion se tiene que el valor x esta en el arreglo, como queremos averiguar en que
posicion i del arreglo esta x, entonces en la especificacion de S aparece como interrogante que valor sera i
(pero aun no sabemos como obtenerlo, solo se menciona que se necesita encontrar ese i, porque solo lo
estamos especificando!) y la poscondicion es que realmente i es un ndice del arreglo y que en esa posicion
si este el valor x que se esta buscando.

A diferencia del ejemplo anterior, el siguiente ejemplo incluye que el ndice a encontrar sea el primero de
todos los ndices del arreglo donde pueda aparecer:

Ejemplo 1.2
Suponga que se quiere especificar el programa que dado un arreglo b[n] encontrar el primer ndice i
(con i en el rango del tamano del arreglo b) donde se encuentra un valor x, la siguiente tripla de Hoare
especificara el programa de manera precisa:

{x b[0 . . . n 1]} i =? {0 i < n x = b[i] (j 0 j < n j i x = b[j] j > i)}

Note que como precondicion se tiene que el valor x esta en el arreglo (pero eso no quiere decir que solo
este una vez), como queremos averiguar la primera posicion posicion i del arreglo esta x, entonces en la
especificacion de S aparece como interrogante que valor sera i (pero aun no sabemos como obtenerlo, solo

2
Especificacion y correccion de algoritmos Especificacion de algoritmos

se menciona que se necesita encontrar ese i, porque solo lo estamos especificando!) y la poscondicion es
que realmente i es un ndice del arreglo y que en esa posicion si este el valor x que se esta buscando, pero
hay una condicion extra y es que si llegan a aparecer otros ndices en el arreglo distintos de i, entonces esos
ndices tienen que ser mayores que i, porque tenemos que asegurar que i es el primero en el que aparece x.

Los siguientes dos ejemplos ilustran algunas estrategias para especificar un algoritmo:

Ejemplo 1.3
Suponga que se quiere especificar un programa que ordene los elementos de un arreglo b[0..n 1] en or-
den ascendente (de menor a mayor). Primero debemos precisar un predicado que nos permita mencionar
el orden de los elementos de un arreglo en otro arreglo (donde vamos a guardar el arreglo original pero
ordenado de manera ascendente), para esto defina P (b, c, n): El arreglo b[0..n 1] es una permutacion del
arreglo c[0..n 1] (es decir los dos arreglos tienen los mismos elementos pero posiblemente en otro orden).

Nuestro objetivo final es guardar los elementos de b[0..n 1] en un arreglo C[0..n 1] que tenga los
mismos elementos de b, pero ordenados de manera ascendente. Por tanto, una poscondicion adecuada sera:
P (b, C, n) (i 0 < i n 1 C[i 1] C[i]), es decir, C es una permutacion de b, (pero por la segunda
condicion) se pide que los elementos de C estan ordenados de manera ascendente. Ahora, la precondicion
debe asegurar que el tamano de ambos arreglos es de mas de un elemento y que C se inicializa con b (pa-
ra modificar a C y no danar el arreglo original), entonces la precondicion sera: (0 n)(C[0..n] = b[0..n]).

De esa manera la tripla de Hoare quedara:

{(0 n) (C[0..n] = b[0..n])} C =? {P (b, C, n) (i 0 < i n 1 C[i 1] C[i])}

Ejemplo 1.4
Suponga que se quiere calcular la suma de los elementos que componene un arreglo b[0..n]. Para esto
debemos solo asegurar que el arreglo si tiene elementos, mas aun hay que asegurar que sus elementos
sean numeros (para el ejemplo vamos a hacerlo solo con numeros enteros, para los otros tipos numeros
es similar), de esa manera nuestra precondicion solo sera: n 1 (i 0 i < n b[i] Z). Como de-
bemos calcular la suma de sus elementos, debemos tener una variable donde almacenemos dicha suma
(llamela x), es decir, que nuestra poscondicion sera que en esa variable esta la suma de los elementos de
b: x = (i 0 i < n b[i]).

Entonces nuestra tripla de Hoare es:

{n 1 (i 0 i < n b[i] Z)} x =? {x = (i 0 i < n b[i])}

3
Especificacion y correccion de algoritmos Correcion de asignacion y condicionales

Seccion 1.3: Correcion de asignacion y condicionales

1.3.1: Correcion de asignaciones

Ahora nos preguntamos como probamos una tripla de Hoare cuando S es una asignacion, dado que
casi siempre cuando se disena un algoritmo hay una parte donde se inicializan variables o se intercambian
valores entre variables. Al decir probar la especificacion nos estamos refiriendo a que si Q es cierta entonces
toca mostrar que R al evaluarse en la asignacion debe ser cierta, para que valga la poscondicion despues
de ejecutarse dicha asignacion. Esto se puede resumir en la siguiente proposicion:

Teorema 1.1
Para mostrar que x = E es una implementacion de {Q} x =? {R} se debe probar que :

Q R[x = E].

El siguiente ejemplo ilustra el resultado anterior:

Ejemplo 1.5
Considere la siguiente tripla de Hoare:

{x > 0} x =? {x > 1}

Una posible implementacion es tomar S como x = x + 1, de esa manera para probar que realmente esa
asignacion es un programa correcto se debe mostrar que la precondicion implique la poscondicion, es decir:

x > 0 (x > 1)[x = x + 1]

Utilizando el metodo de demostracion de asumir el antecedente entonces tomaremos x > 0 como verdad y
demostraremos que (x > 1)[x = x + 1] vale:

(x > 1)[x = x + 1]
= Sustitucion textual
x+1>1
= Aritmetica
x>0
= Hipotesis
true

Del teorema anterior podemos calcular una precondicion Q a partir de una poscondicion R, como?, es
bastante sencillo, dado que la precondicion mas debil que cumple el teorema es la misma consecuencia del
teorema. Es decir, para una asignacion x = E la precondicion mas debil para llegar a la poscondicion R

4
Especificacion y correccion de algoritmos Correcion de asignacion y condicionales

es R[x = E], dado que R[x = E] R[x = E] se cumple trivialmente. Este resultado nos permite resolver
las especificaciones de programas que tienen la siguiente tripla de Hoare:

{?} x = E {R}

Los ejemplos a continuacion muestran como obtener la precondicion mas debil basados en una asignacion
y una poscondicion:

Ejemplo 1.6
Hallar la precondicion mas debil Q que hace valida la siguiente tripla de Hoare:

{?} q, r = q + 1, r y {q y + r = x}

Para solucionarlo tenemos que hallar R[x = E] (dado que esta es la precondicion mas debil de una
asignacion), de esa manera se tiene la siguiente demostracion:

(q y + r = x) [q, r = q + 1, r y]
= Sustitucion textual
(q + 1) y + (r y) = x
= Aritmetica
(q y + y + r y) = x
= Aritmetica
qy+r =x
De esa manera Q (q y + r = x).

Ejemplo 1.7
Hallar la precondicion mas debil Q que hace valida la siguiente tripla de Hoare:

{?} y = 5 + y {x = y}

Para solucionarlo tenemos que hallar R[x = E] (dado que esta es la precondicion mas debil de una
asignacion), de esa manera se tiene la siguiente demostracion:

(x = y) [y = 5 + y]
= Sustitucion textual
x=y+5
De esa manera Q (x = y + 5).

Tambien sabemos que en un programa pueden haber asignaciones de manera consecutiva:

{Q} x1 = E1 , x2 = E2 . . . , xn = En {R}

De esa manera el Teorema 1.1 se puede generalizar de la siguiente forma:

Teorema 1.2
Para mostrar que x1 = E1 , x2 = E2 . . . xn = En es una implementacion de {Q} x1 =?, x2 =?, . . . xn =? {R}
se debe probar que:

5
Especificacion y correccion de algoritmos Correcion de asignacion y condicionales

Q R[xn = En ][xn1 = En1 ] . . . [x1 = E1 ]

La demostracion de este teorema es bastante sencilla dado que la ejecucion de cada asignacion es lineal y
se debe asegurar que en cada una de las asignaciones se obtenga la precondicion mas debil para la siguiente
asignacion, razon por la cual el teorema dice que toca demostrar la poscondicion pero con las asignaciones
al contrario a como se ejecutan (trate de escribir una demostracion formal del teorema).

En los siguientes ejemplos se ilustra como demostrar asignaciones mutiples utilizando el teorema an-
terior:

Ejemplo 1.8
Demostrar que la siguiente tripla de Hoare es correcta:

{0 = y} x = x + 1 ; y = x + y {x = y}

Utilizando el teorema anterior, tenemos que mostrar que y = 0 (x = y)[y = x+y][x = x+1]. Entonces
utilizando por metodo directo supongamos que y = 0 y mostremos que (x = y)[y = x + y][x = x + 1]:

(x = y)[y = x + y][x = x + 1]
= Sustitucion textual
(x = y + x)[x = x + 1]
= Sustitucion textual
x+1=y+x+1
= Aritmetica
y=0
= Hipotesis
T rue

Ejemplo 1.9
Demostrar que la siguiente tripla de Hoare es correcta:

{x = A y = B} x = x y; y = x + y; x = y x {x = B y = A}

Utilizando el teorema anterior, tenemos que mostrar que:

x = A y = B (x = B y = A)[x = y x][y = x + y][x = x y]

Entonces utilizando por metodo directo supongamos que x = A y = B y mostremos que (x = B y =


A)[x = y x][y = x + y][x = x y]:

6
Especificacion y correccion de algoritmos Correcion de asignacion y condicionales

(x = B y = A)[x = y x][y = x + y][x = x y]


= Sustitucion textual
(y x = B y = A)[y = x + y][x = x y]
= Sustitucion textual y aritmetica
(y = B x + y = A)[x = x y]
= Sustitucion textual
y = B (x y) + y = A)
= Aritmetica
y =Bx=A
= Hipotesis
T rue

Para terminar con esta seccion de correccion de asignaciones, el siguiente ejemplo ilustra como utilizar los
teoremas mencionados con anterioridad para deducir el valor de una asignacion:

Ejemplo 1.10
Se quiere determinar E de manera que la siguiente tripla sea valida:
{i = j} i, j = i + 1, E {i = j}
Intuitivamente, E sera j + 1, pues el razonamiento del programa sera: Partimos de i = j, entonces al
sumar uno a ambos lados tenemos que i + 1 = j + 1, es decir que los nuevos valores de i, j siguen siendo
iguales, pero vamos a justificarlo con nuestros teoremas. Sabemos que el hecho que la tripla sea valida
significa que Q (i = j)[i, j = i + 1, E].

Podemos manipular dicha implicacion (por lo general lo haremos de esta manera), asumiendo la premisa
cierta (en este caso la premisa es i = j), de modo que la conclusion sera cierta:

T rue
= Suposicion hecha que conclusion es cierta
(i = j)[i, j = i + 1, E]
= Sustitucion textual
(i + 1 = E)
= Sustitucion textual por premisa i = j
(j + 1 = E)

Luego E = j + 1 hace cierta la implicacion, como queramos verificar.

1.3.2: Correccion de condicionales

Recordemos que en todos los algoritmos que solucionen un problema de programacion hacen uso de
condiciones para ejecutar o validar un conjunto de acciones. De esa manera tambien existen herramientas
para demostrar la correccion de estos, para esto primero definamos formalmente que es un condicional.

7
Especificacion y correccion de algoritmos Correcion de asignacion y condicionales

La instruccion condicional se llama y se representa como IF y tiene la siguiente forma en muchos


lenguajes de programacion:
IF if B then S1 else S2
Donde B es una expresion booleana, y S1 y S2 son dos programas que se ejecutan segun el valor de B,
si B es cierta entonces se ejecutara S1 de lo contrario se ejecutara S2 .

Ahora, supongamos que se quiere la ejecucion de un condicional inicie en un estado que satisface la
precondicion Q para llegar a una poscondicion R, es decir {Q} IF {R}, nos preguntamos entonces como
se hace para garantizar que {Q} IF {R} sea valida. Note primero que cuando B es cierta entonces S1 se
ejecutara, de esa manera S1 tiene que hacer verdad a R; por otro lado si B es falsa (o lo que es lo mismo
B es verdad), se ejecutara S2 , as que S2 debe hacer verdad a R. En pocas palabras se cumple la siguiente
especificacion:

{Q}
if B then {Q B} S1 {R}
else {Q B} S2 {R}
{R}
De esa manera podemos enunciar el siguiente teorema para la verificacion de la correccion de condi-
cionales:

Teorema 1.3
Para probar que {Q} IF {R}, es suficiente con probar:

a) {Q B} S1 {R}.

b) {Q B} S2 {R}.

En los siguientes ejemplos se ilustra el uso del teorema anterior:

Ejemplo 1.11
Considere el siguiente algoritmo:

{true}
if x y then skip
else x, y = y, x
{x y}
Usando el Teorema 1.3 tocara probar:

a) {true x y} skip {x y}
b) {true (x y)} x, y = y, x {x y}
Para probar a) probemos que (true x y) (x y) dado que el programa skip no realiza ningun
tipo de accion sobre las variables de la precondicion. De esa manera por metodo directo supongamos que la
precondicion es cierta, es decir que x y es verdad, pero como p p entonces se tiene que la poscondicion

8
Especificacion y correccion de algoritmos Correcion de asignacion y condicionales

es necesariamente cierta (porque es la misma hipotesis).

Pero para probar b), dado que es una asignacion debemos utilizar el Teorema 1.1. De esa manera toca
demostrar que:
(x y) x y[x, y = y, x]

Entonces por metodo directo supongamos que (x y) y mostremos el consecuente:

x y[x, y = y, x]
= Sustitucion textual
yx
= y x y < x y = x
y <xy =x
= Hipotesis:(x y) y < x
true y = x
= Cero del
T rue

Ejemplo 1.12
Verifique la correccion del siguiente programa, suponiendo que a y b son variables booleanas:

{Q:True}
if B1 a b then a = a
[]B2 a b then b = b
fi
{R a b}

Note que esta notacion del condicional primero abre con un if y cierra con un fi, dado que en su interior
hay dos condicionales; pero el segundo no es la negacion del primero, de esa forma que no podamos usar
el else con el que hemos venido trabajando. Ademas, note que por cada condicion que este dentro del
condicional debe tener un programa a ejecutar, lo unico que faltara probar es que alguna de las dos
condiciones sea verdadera para que de esa manera se pueda ejecutar al menos uno de los programas
asociados.
Para esto necesitamos verificar dos cosas. En primer lugar, que las guardas del condicional agotan
todas las posibilidades dadas por la precondicion (en otras palabras que en cualquier instancia donde la
precondicion se cumple, existe por lo menos un caso del condicional al cual se entra). En segundo lugar, que
en cada caso del condicional, la ejecucion del codigo correspondiente llega a un estado donde la poscondicion
se cumple.

1. Agotamiento de casos (alguna de las condiciones se cumple) Q (B1 B2 ):

9
Especificacion y correccion de algoritmos Correccion de ciclos

true (a b) (a b)
= Simetra de y asociatividad de
true (a a) (b b)
= Tercero excluido
true true true
= Definicion de disyuncion e implicacion
true

2. Verificacion que la tripla {true (a b)} a = a {a b} es correcta, para esto supongamos que
true (a b) y mostremos que (a b)[a = a]:

(a b)[a = a]
= Sustitucion
a b
= Hipotesis
T rue

3. Verificacion que la tripla {true (a b)} b = b {a b} es correcta, para esto supongamos que
true (a b) y mostremos que (a b)[b = b]:

(a b)[b = b]
= Sustitucion
a b
= Hipotesis
T rue

Seccion 1.4: Correccion de ciclos

En computacion constantemente estamos usando ciclos para hacer tareas repetitivas en un algoritmo.
Una de las aplicaciones del principio de induccion es demostrar que el diseno de un ciclo es correcto de tal
manera que haga lo que tiene que hacer y si lo hace que lo haga bien.

Cuando se disena un ciclo dentro de un algoritmo se debe tener en cuenta distintos elementos. En pri-
mer lugar se debe contemplar la precondicion y la poscondicion, en segundo lugar el mismo ciclo tiene unas
condiciones especiales para ejecutarse y realizar la accion para la cual se diseno, la condicion que obliga
al ciclo a seguir se conoce como guarda y las instrucciones que ejecuta en cada iteracion se se denominan
operaciones (dado que pueden ser asignaciones, productos, condiciones, entre otras). El ultimo elemento a

10
Especificacion y correccion de algoritmos Correccion de ciclos

tener en cuenta en la definicion de un ciclo es el invariante, que tal como su nombre lo indica es algo que
no cambia durante la ejecucion del ciclo, es lo que el ciclo asegura en cada iteracion.

Antes de dar un ejemplo, vamos a mostrar como cada parte mencionada con anterioridad se representa
de manera formal. Un ciclo se escribe de la siguiente manera:
do B S od
A continuacion mostramos un ejemplo de una especificacion de un ciclo y de esa manera probar luego que
esta especificacion es correcto:
{Q 0 n}
i, p = 0, 0;
{P 0 i n p = i x}
do i n i, p = i + 1, p + x od
{R p = n x}
Note que el programa anterior solo suma n veces un valor x y lo almacena en p. Sin embargo para que el
programa anterior sea correcto debemos mostrar varias cosas, pero por ahora enfoquemonos en demostrar
que la invariante del ciclo se preserva, para esto enunciaremos a continuacion el teorema fundamental
del invariante:

Teorema 1.4
Suponga las siguiente proposiciones:
{P B} S {P } o lo que es lo mismo que la ejecucion de S inicia en estado donde P y B son verdad
y termina en un estado en la que P es verdad.

{P }do B S od{true} o lo que es lo mismo que el ciclo que inicia con P cierta, en algun momento
termina en un numero finito de pasos.
Entonces, {P }do B S od{P B} vale.

Una demostracion sencilla es la siguiente, primero note que por la segunda hipotesis del teorema se asegura
que el ciclo termina en un numero finito de iteraciones, digamos n (n 0), toca es probar que realmente
cuando el ciclo termina vale {P B}. Mostrar que B es verdadera es sencillo pues el ciclo termina si la
guarda es falsa, es decir, B es falso o lo que es lo mismo B es cierto. Solo restara probar que P es cierta
cuando el ciclo termina, es decir cuando las n iteraciones se han ejecutado. Para esto usamos induccion,
pues hay n iteraciones en las cuales se debe cumplir la invariante P , el caso base es facil pues por la segunda
hipotesis para que se inicie a ejecutar el ciclo P tiene que ser cierta, ahora demostremos el caso inductivo
para eso supongamos que P es cierta en la iteracion i (i < n) y mostremos que sigue siendo cierta en la
iteracion i + 1. Note que en la iteracion i + 1 para que se ejecute S debe ser cierto P y B, y usando la
primera hipotesis se tiene que despues de la iteracion i + 1 sigue siendo cierta.

Este teorema es muy importante dado que nos asegura que demostrando las condiciones a) y b) se tiene
que el ciclo involucrado es correcto ya que su invariante se preserva durante toda su ejecucion (incluyendo
la ultima) y que la guarda en algun momento llega a ser falsa, es decir que termina. Pero, note que si el ciclo
tiene una poscondicion que deba cumplir cuando termine de ejecutarse se debe mostrar que P B R,
pues las condiciones en las que termina deben implicar la poscondicion. De la misma manera cuando se

11
Especificacion y correccion de algoritmos Correccion de ciclos

tiene una precondicion, esta como mnimo debe implicar la invariante, dado que esta debe ser verdad antes
de que dicho ciclo se inicie a ejecutar.

A continuacion ilustramos con un ejemplo la manera de utilizar el teorema anterior para demostrar
que un ciclo es correcto:

Ejemplo 1.13
En este ejemplo ilustraremos como utilizar el Teorema 1.4, para esto considere el siguiente ciclo:

{P 0 i n p = i x}
do i n i, p = i + 1, p + x od
{P i = n}
Entonces para mostrar que el invariante se preserva necesitamos mostrar que las dos hipotesis del
teorema se cumplen y de esa manera por el teorema podemos afirmar que la invariante se cumple. Primero
,se tiene que probar que {P B} i, p = i + 1, p + x {P }, para eso utilizamos el Teorema 1.1 que nos dice que
tenemos que probar para que la tripla de Hoare con una asignacion sea correcta, de esa manera lo que hay
que probar se resume en probar la siguiente proposicion:

P B P [i, p = i + 1, p + x].

Cuya demostracion es la siguiente:

P [i, p = i + 1, p + x]
= Sustitucion textual
0 i + 1 n p + x = (i + 1) x
= Aritmetica
1 i n p = i x
Aritmetica
i 0 i n p = i x
= Definicion de B y P
BP

Ahora para probar la segunda hipotesis toca asegurar que el ciclo termina, pero es claro que el ciclo
termina, dado que i incrementa en 1 en cada iteracion y como la invariante se preserva se tiene que 0 i n,
entonces despues de n iteraciones el ciclo termina porque i = n (la guarda se vuelve falsa).

Con el ejemplo anterior y con todo lo dicho anteriormente se puede resumir los pasos de la correcion de
ciclos en una lista de chequeo:

Lista de chequeo:

a) La invariante P es cierta antes de que se inicie el ciclo.

b) La invariante P se preserva dentro del ciclo: {P B} S {P }.

12
Especificacion y correccion de algoritmos Correccion de ciclos

c) El ciclo termina.
d) La poscondicion R del programa vale despues de que termina el ciclo: P B R

Probando la terminacion de ciclos


Para probar que un ciclo termina se debe proponer una funcion T acotada, de tal manera que por cada
iteracion esta se reduce y que ademas sino es la ultima iteracion la funcion T debe ser positiva.

Teorema 1.5
Para probar que:

{ Invariante P }
{ Funcion acotada T }
do B S od
Termina, es suficiente con encontrar una funcion acotada T , es decir, una expresion entera que es una
cota superior al numero de iteraciones que aun faltan por ejecutarse. As esta funcion T satisface:
a) T se decrementa en cada iteracion: eso es para v variable fresca se tiene
{P B} v = T {T < v}

b) Siempre que haya una iteracion mas por hacer, T > 0:


P B T >0

Ejemplo 1.14
Para ilustrar este teorema considere el ciclo propuesto en el Ejemplo 1.13:

{P 0 i n p = i x}
{T n i}
do i n i, p = i + 1, p + x od
{P i = n}
Note que en cada iteracion i decrementa en una y de esa manera decrementa nuestra funcion T tambien
en uno. Ademas necesitamos probar que P B T > 0:
0 i n p + x = (i) x i n
Debilitamiento
inin
= Aritmetica
0<ni
= Definicion de T
0<T

13
Especificacion y correccion de algoritmos Correccion de ciclos

Los siguientes ejemplos ilustran como demostrar que un ciclo es correcto:

Ejemplo 1.15
Considere el siguiente algoritmo:

{n 0}
x, r = 0, 1
do x < n r, x = 2r, x + 1 od
{r = 2n }
Para este algoritmo vamos a encontrar la funcion cota con la que se asegurara que el ciclo termina,
vamos a ver la preservacion de la invariante y por ultimo vamos a ver que cuando el ciclo termina, este
termina bien; es decir, que la poscondicion se cumple.

1. Funcion cota: n x.
Note que a medida que el ciclo avanza, la distancia disminuye en 1 ya que x aumenta en 1 y n es una
constante. Ademas el numero natural n x siempre es mayor que cero por la guarda del ciclo.

2. Invariante: r = 2x x n.
Demostracion por induccion sobre el numero de veces que se ha entrado al ciclo.

Caso base: Justo antes de entrar al ciclo, r = 1, x = 0. Claramente 1 = 20 , as que se cumple la


ecuacion. Ademas, 0 n debido a la precondicion, as que la desigualdad r x se cumple.
Paso inductivo: Supongamos que en algun momento dado, se cumplio el invariante con las
variables x, r; esta es mi hipotesis. Quiero explicar que se sigue cumpliendo con los nuevos
valores de x y r; para distinguirlos, se usara rnuevo , xnuevo para esos nuevos valores.
As que vamos a verificar que
rnuevo = 2xnuevo xnuevo n

Veamos:
rnuevo
= Asignacion r = 2r en cuerpo de ciclo
2r
= Hipotesis de induccion
2 2x
= Aritmetica
x+1
2
= Asignacion x = x + 1 en cuerpo de ciclo
xnuevo
2

Por otro lado, la condicion xnuevo n es cierta porque la guarda del ciclo afirma que x < n,
as que si incrementamos 1 a x, claramente el nuevo valor de x es menor o igual que n. Esto
prueba el paso inductivo y por tanto concluimos que el invariante vale durante el ciclo.

14
Especificacion y correccion de algoritmos Ejercicios

3. Terminacion de ciclo: Dada la negacion de la condicion de entrada x n y el invariante r = 2x


y x n tenemos que x = n. Ahora reemplazando x en la ecuacion r = 2x , obtenemos r = 2n que es
exactamente la poscondicion del programa.

Seccion 1.5: Ejercicios

1. Especifique de forma precisa los siguientes problemas de programacion:

a) Calcular la suma de los elementos del arreglo b[j . . . k 1].


b) Obtener el maximo valor de un arreglo b[j . . . k 1].
c) Obtener el ndice donde se encuentra el maximo valor de un arreglo b[j . . . k 1].
d) Almacene en un arreglo c[0 . . . n 1] una ordenacion de un arreglo b[0 . . . n 1]. Establezca los
predicados que considere necesarios.
e) Calcule la mayor potencia de dos que no sea mayor que un n dado.
f) Contar el numero de ceros que hay en un arreglo b[0 . . . n 1].
g) Suponga que se tiene un arreglo b[0 . . . n 1]. Cada uno de sus segmentos b[i . . . j 1] tiene una
suma. Calcule la suma mas grande que se puede obtener de los segmentos del arreglo original.
h) Obtenga el promedio de los valores almacenados en un arreglo b[0 . . . n 1].
i) Obtenga la media de los valores almacenados en un arreglo b[0 . . . n 1].
j) Considere un arreglo b[0 . . . n 1] cuyos valores son uno o cero (como si fuera un arreglo de bits)
y obtenga el numero decimal asociado a ese arreglo b.
k) Un arreglo b tiene la lista de estudiantes que estan en la clase de elementos y el arreglo c tiene
la lista de las personas que trabajan en el Politecnico. Encuentre la primera persona que esta en
b y c.
l) Considere un arreglo b ordenado de cierta manera, encuentre el ndice mas grande del arreglo
donde se encuentra el valor x.
m) Diga si es cierto que dado un arreglo b, este tiene un valor negativo.
n) Calcule el doble de cada uno de los elementos de un arreglo b[0 . . . n 1].
o) Ordene un arreglo de enteros b[0 . . . n 1].
p) Encuentre el valor maximo y mnimo de un arreglo b[0 . . . n 1].
q) Invierta el arreglo b[0 . . . n 1].
r) Intercambie los valores del arreglo b[0 . . . n 1] con los elementos del arreglo c[0 . . . n 1].
s) Un arreglo b[0 . . . n 1] tiene valores rojos, blancos y azules. Ponga los rojos en los primeros
ndices del arreglo, luego los azules y por ultimo los blancos.

15
Especificacion y correccion de algoritmos Ejercicios

t) Permute los valores de un arreglo b, de tal manera que los numeros menores de un x esten de
primeras y luego los que son mayores, e indique el ndice donde se encuentra el ultimo valor
menor que x.
u Dado un arreglo booleano b que contenga un valor verdadero, encuentre el ndice mas grande
en que b tenga un valor verdadero. Ademas encuentre el ndice mas pequeno en que b tenga un
valor verdader.
v Calcule el numero de veces que un arreglo de enteros b tiene un valor x.
x Para un arreglo de enteros b que tenga un valor maximo, encuentre el segundo valor mas grande
que tiene almacenado.

2. Calcule y simplifique la precondicion mas debil de la siguiente especificacion:

{?} x = x + y, y = x y, x = x y {x = X y = Y }

3. Calcule y simplifique la precondicion mas debil para la siguiente especificacion:

{?} x = x / y, y = x / y, x = x / y {x X y Y }

4. Suponga que el numero de peras que Mara y Juan tienen (representadas por m y j respectivamente)
estan relacionados por la siguiente formula (C es una constante): P C = m + 2 j. Encuentre una
solucion para e en la especificacion {P par.m} m, j = m 2, e {P }.

5. Teniendo en cuenta la definicion de los numeros de Fibonacci vistos en el captulo anterior, se define
el siguiente predicado P n > 0 a = Fn b = fn1 . Encuentre una solucion para e y f en {P } n, a, b =
n + 1, e, f {P }.

6. Determine la precondicion mas debil que satisfaga las siguientes especificaciones:

a) {?} x = x x {x > 0}.


b) {?} x = x + 1 {x3 5x2 + 2x > 0}.
c) {?} x, y = x + 1, y 1 {x + y > 0}.
d) {?} x, y = y + 1, x 1 {x > 0}.
e) {?} x, y = y x, x y {x + y > 0}.
f) {?} a = a b {a}.
g) {?} a = a b {a b}.

7. Demuestre que el siguiente programa es correcto:

{x > 5}
if x y then skip
else x, y = y, x
{x y}

16
Especificacion y correccion de algoritmos Ejercicios

8. Demuestre que el siguiente programa es correcto:

{x = X}
if x < 0 then x = x
else skip
{x = abs.X}

Donde abs.x es el valor absoluto de x.

9. Demuestre que el siguiente programa es correcto:

{y > 0 z xy = X}
if impar.y then z, y = z x, y 1
else x, y = x x, y/2
{y 0 z xy = X}

10. Demuestre que el siguiente programa es correcto:

{true}
if x 1 then x = x + 1
else x = x 1
{x 1}

11. Demuestre que el siguiente programa es correcto:

{true}
x, y = y y, x x
if x y then x = x y
else y = y x
{x 0 y 0}

12. Encuentre la precondicion mas debil del siguente algoritmo:

{?}
x = x + 1
if x 0 then x = x 1
if x 0 then x = x + 2
if x = 1 then skip
{x 1}

13. Para los siguientes programas debe mostrar que esta correcto usando la lista de chequeo propuesta
en el captulo:

a) Este algoritmo almacena la suma de los numeros almacenados en un arreglo b[0 . . . n 1] para
n 0:

17
Especificacion y correccion de algoritmos Ejercicios

{Q 0 n}
x, k = 0, 0;
{P 0 k n x = (i 0 i < k b[i])}
do k n x, k = x + b[k], k + 1 od
{R x = (i 0 i < n b[i])}

b) Este algoritmo calcula el numero de Fibonacci para un n dado:

{Q 0 n}
k, b, c = 0, 1, 0;
{P 0 k n b = Fk1 c = Fk }
do k n k, b, c = k + 1, c, b + c od
{R c = Fn }
Porque b inicia en 1?.
c) Este algoritmo almacena la suma de los numeros almacenados en un arreglo b[0 . . . n 1] para
n 0:

{Q 0 n}
x, k = 0, n;
{P 0 k n x = (i k i < n b[i])}
do k 0 x, k = x + b[k 1], k 1 od
{R x = (i 0 i < n b[i])}
Que diferencias tiene con el ejercicio del literal a) ?.

14. Demuestre que el siguiente algoritmo (para calcular la multiplicacion rusa) es correcto:

{T rue}
x, y, r = A, B, 0;
do x 0
if x mod 2 = 0 x, r = x 1, r + y;
[] x mod 2 = 1 x, y = x/2, 2y;
fi
od
{r = ab}

Para esto defina claramente la funcion cota, la invariante y como a la terminacion del ciclo se cumple
la poscondicion.

15. Escriba el algoritmo para realizar el acercamiento de tres numeros (x, y, z) y demuestre que este
es correcto. Nota: Especifique claramente el ciclo involucrado en este algoritmo, su invariante y su
funcion cota.

16. Escriba el algoritmo para encontrar el maximo comun diviso de dos numeros (x, y) y demuestre que
este es correcto. Nota: Especifique claramente el ciclo involucrado en este algoritmo, su invariante y
su funcion cota.

18
Especificacion y correccion de algoritmos Ejercicios

17. Escriba el algoritmo que implemente el algoritmo de euclides y demuestre que este es correcto. Nota:
Especifique claramente el ciclo involucrado en este algoritmo, su invariante y su funcion cota.

18. Escriba el algoritmo para que dado un natural fijo N diga si existen a, b N tal que N = a.b y
demuestre que este es correcto. Nota: Especifique claramente el ciclo involucrado en este algoritmo,
su invariante y su funcion cota.

19. Escriba el algoritmo que calcule la potencia n de un numero dado y demuestre que este es correcto.
Nota: Especifique claramente el ciclo involucrado en este algoritmo, su invariante y su funcion cota.

20. Escriba el algoritmo que calcule el factorial de un numero dado y demuestre que este es correcto.
Nota: Especifique claramente el ciclo involucrado en este algoritmo, su invariante y su funcion cota.

21. Escriba el algoritmo para calcular el producto de dos matrices y demuestre que este es correcto.
Nota: Especifique claramente el ciclo involucrado en este algoritmo, su invariante y su funcion cota.

22. Escriba el algoritmo que encuentre los numeros de Lucas (definidos en los ejercicios del captulo de
induccion) y demuestre que este es correcto. Nota: Especifique claramente el ciclo involucrado en
este algoritmo, su invariante y su funcion cota.

23. Escriba el algoritmo que dado un numero N calcule el numero binario asociado y demuestre que este
es correcto. Nota: Especifique claramente el ciclo involucrado en este algoritmo, su invariante y su
funcion cota.

24. Escriba el algortmo para sumar dos matrices y demuestre que este es correcto. Nota: Especifique
claramente el ciclo involucrado en este algoritmo, su invariante y su funcion cota.

19
Especificacion y correccion de algoritmos Ejercicios

20
Bibliografa

[1] David Gries y Fred B. Schneider. A logical approach to discrete Math. Springer, 1994.

21

Вам также может понравиться