Está en la página 1de 15

Unidad 1 / Escenario 2

Lectura fundamental

Corrección de programas

Contenido

1 Precondición más débil de instrucciones simples

2 Ejemplos de verificación de corrección de programas

3 Resumen

Palabras clave: programa, corrección de programas, precondición más débil, triplas de Hoare.
En esta lectura se demuestra el proceso de verificación de la corrección de un programa construido a
partir de estructuras fundamentales de programación. La sección 1 formula la precondición más débil
de instrucciones vacías, asignaciones, condicionales y de programas constituidos por composición de
estas operaciones. La sección 2 presenta un conjunto de ejemplos de demostración de corrección de
programas a partir de los resultados de la sección 1.

1. Precondición más débil de instrucciones simples


A continuación se estudiarán las fórmulas para derivar la precondición más débil de instrucciones
básicas fundamentales de los lenguajes de programación imperativos (Hoare, 1969) (Kaldewaij,
1990).

1.1. Instrucción vacía

En la mayor parte de los lenguajes de programación no existe una instrucción diseñada con la
intención de no tener efecto alguno sobre el estado o la ejecución del programa; al hablar de
instrucción vacía se hace referencia generalmente a la ausencia de instrucciones. El siguiente ejemplo
presenta un programa que contiene una instrucción vacía (un bloque de código vacío):

Ejemplo 1. El programa reemplaza el valor de la variable de entrada con su correspondiente


valor absoluto. Cuando a≥0, la variable tiene ya el valor deseado y por tanto el bloque de código
respectivo se encuentra vacío.

{Pre Q: a = A}
program ejemplo_inst_vacia
 input: a:ℤ
 if a ≥ 0 then
   //bloque vacío
 else
   a := -a
 return a
{Pos R: a = |A|}

POLITÉCNICO GRANCOLOMBIANO 2
Considérese la tripla {Q}<vacío>{R}. Dado que la instrucción vacía no modifica el estado del
programa, la poscondición debería ser satisfecha antes de la ejecución. Esto quiere decir que todo
estado que cumple Q, también debe cumplir Q:

[Q ⇒ R]

Además, el predicado Q más débil que satisface [Q ⇒ R] es R:


wp(<vacío>, R) ≡ R

1.2. Asignación

Una asignación es una instrucción de la forma <var>:=<exp>, que reemplaza el valor de la variable
<var> por el resultado de la evaluación de la expresión <exp>. La asignación es la única operación
que modifica de manera directa el estado del programa.

Considérese la tripla {Q}x:=E{R}. La única diferencia entre el estado inicial y el estado final del
programa es que, en el segundo, x es reemplazada por el valor de E. Esto quiere decir que todo estado
que cumple Q también cumple R(x:=E):

[Q ⇒ R(x:=E)]

Además, el predicado Q más débil que satisface [Q ⇒ R(x:=E)] es R(x:=E):

wp(x:=E, R) ≡ R(x:=E)

1.3. Instrucción condicional

Una instrucción condicional tiene la forma

if <condición C> then


<conjunto de instrucciones A>
else
<conjunto de instrucciones B>

POLITÉCNICO GRANCOLOMBIANO 3
y permite a un programa decidir entre dos conjuntos de pasos a ejecutar (A o B) de acuerdo con
el valor de verdad de una expresión lógica (C). Si C es verdadero, se ejecutará A, en caso contrario,
se ejecutará B.

Considérese la tripla {Q}if C then A else B{R}. Independientemente de si se satisface


C (y, por tanto, se ejecuta A) o no (y, por tanto, se ejecuta B), se debe garantizar que al finalizar la
ejecución del condicional se satisface R. Puede entonces dividirse el análisis en dos casos:

i. Se satisface C, luego después de la ejecución de A se debe satisfacer R:


{Q ∧ C}A{R}

Esta tripla es equivalente a (por traslación)


[Q ∧ C ⇒ wp(A, R)]

que a su vez es equivalente a


[Q ⇒ (C ⇒ wp(A, R))]

ii. No se satisface C, luego después de la ejecución de B se debe satisfacer R:


{Q ∧ ¬C}B{R}

Esta tripla es equivalente a


[Q ∧ ¬C ⇒ wp(B, R)]

que a su vez es equivalente a (por traslación)


[Q ⇒ (¬C ⇒ wp(B, R))]

Al unir las conclusiones de I y II se tiene que para que el programa sea correcto debe cumplirse

[Q ⇒ ((C ⇒ wp(A, R)) ∧ (¬C ⇒ wp(B, R)))]

por lo tanto,
wp(if C then A else B, R) ≡ ((C ⇒ wp(A, R)) ∧ (¬C ⇒ wp(B, R)))

POLITÉCNICO GRANCOLOMBIANO 4
1.4. Composición secuencial

Puede entenderse un programa como la composición de un conjunto de instrucciones, las cuales son
ejecutadas secuencialmente, una después de la otra:

<instrucción 1>
<instrucción 2>

<instrucción k>

Para derivar la precondición más débil de dicho programa introduciremos una aserción adicional P que
deberá satisfacerse justo antes de la ejecución de la última instrucción:

{Q}
<instrucción 1>
<instrucción 2>

<instrucción k-1>
{P}
<instrucción k>
{R}

Esto nos permite dividir el problema de verificación de corrección de nuestro programa en dos
problemas distintos:

{Q} {P}
<instrucción 1> <instrucción k>
<instrucción 2> {R}

<instrucción k-1>
{P}

Note que para que Q sea lo más débil posible sin afectar la corrección del programa, P debe ser
también lo más débil posible. Esto es
P ≡ wp(<instrucción k>, R)

Verificar la corrección del programa se reduce entonces a demostrar la validez de la tripla

POLITÉCNICO GRANCOLOMBIANO 5
{Q}
<instrucción 1>
<instrucción 2>

<instrucción k-1>
{wp(<instrucción k>, R)}

Usando la misma lógica, el problema puede a su vez reducirse a


{Q}
<instrucción 1>
<instrucción 2>

<instrucción k-2>
{wp(<instrucción k-1>, wp(<instrucción k>, R))}

Siguiendo el mismo proceso k veces, se llega a una tripla cuyo programa corresponde a una
instrucción vacía
{Q}

<vacía>

{wp(<instrucción 1>, wp(<instrucción 2>, wp(<instrucción 3>, ...)))}

Por lo tanto,
wp(<instrucción 1><instrucción 2>...<instrucción k>, R) ≡

wp(<instrucción 1>, wp(<instrucción 2>, … wp(<instrucción k>, R) … ))

Como casos particulares, para k = 2 la precondición más débil es


wp(<instrucción 1>, wp(<instrucción 2>, R))

y para k = 3
wp(<instrucción 1>, wp(<instrucción 2>, wp(<instrucción 3>, R)))

POLITÉCNICO GRANCOLOMBIANO 6
2. Ejemplos de verificación de corrección de programas
A continuación, se presentan ejemplos de verificación de corrección de programas a partir de los
resultados presentados anteriormente:

Ejemplo 2. Demostrar o refutar que es válida la tripla

{Pre Q: true}
program ejemplo_2
 input: x:ℝ
 return x
{Pos R: x2 ≥ 0}

En este caso, el programa consiste en una instrucción vacía (la declaración de variables y la instrucción
de retorno definen las entradas y salidas, pero no tiene efecto sobre el estado del programa). Tenemos
entonces que

   {true}<vacío>{x2 ≥ 0}

≡  [true ⇒ wp(<vacío>, x2 ≥ 0)]

≡  [true ⇒ x2 ≥ 0]

≡  [true ⇒ true]

≡  true

Concluimos que el programa es correcto con respecto a su especificación.

POLITÉCNICO GRANCOLOMBIANO 7
Ejemplo 3. Demostrar o refutar que es válida la tripla

{Pre Q: true}
program ejemplo_3
 input: x:ℝ
 return x
{Pos R: x2 ≥ x}

Tenemos que

   {true}<vacío>{x2 ≥ x}

≡  [true ⇒ wp(<vacío>, x2 ≥ x)]

≡  [true ⇒ x2  ≥ x]                           ( aplicando (true ⇒ p) ≡ p )

≡  [x2 ≥ x]                            ( usando como contraejemplo x = 0.5 )

≡  false

Concluimos que el programa no es correcto con respecto a su especificación.

POLITÉCNICO GRANCOLOMBIANO 8
Ejemplo 4. Demostrar o refutar que es válida la tripla

{Pre Q: true}
program ejemplo_4
 input: x:ℝ
 x := x*x + 1
 return x
{Pos R: x2 ≥ x}

Tenemos que

   {true}x := x*x + 1{x2 ≥ x}


≡  [true ⇒ wp(x := x*x + 1, x2 ≥ x)]

≡  [true ⇒ (x*x + 1)2 ≥ x*x + 1]              ( aplicando (true ⇒ p) ≡ p )          


≡  [(x*x + 1)2 ≥ x*x + 1]

≡  [(x2 + 1)2 ≥ x2 + 1]

≡  [(x2)2 + 2x2 + 1 ≥ x2 + 1]

≡  [(x2)2 + 2x2 + 1 - x2 + 1 ≥ x2 + 1 - x2 + 1]

≡  [(x2)2 + x2 ≥ 0]

≡  true

Concluimos que el programa es correcto con respecto a su especificación.

POLITÉCNICO GRANCOLOMBIANO 9
Ejemplo 5. Demostrar o refutar que es válida la tripla

{Pre Q: a = A}
program ejemplo_5
 input: a:ℤ
 if a ≥ 0 then
   //bloque vacío
 else
   a := -a
 return a
{Pos R: a = |A|}

Tenemos que

   {a = A} if a ≥ 0 then <vacío> else a := -a {a = |A|}

≡  [a = A ⇒ wp(if a ≥ 0 then <vacío> else a := -a, a = |A|)]

≡  [a=A ⇒ ((a≥0 ⇒ wp(<vacío>, a=|A|)) ∧ (¬(a≥0) ⇒ wp(a:=-a, a=|A|)))]

≡  [a=A ⇒ ((a≥0 ⇒ a=|A|) ∧ (a<0 ⇒ -a=|A|))]   ( suponiendo el antecedente )          

≡  [(A≥0 ⇒ A=|A|) ∧ (A<0 ⇒ -A=|A|)]                   ( definición de |A| )          

≡  true

Concluimos que el programa es correcto con respecto a su especificación.

POLITÉCNICO GRANCOLOMBIANO 10
Ejemplo 6. Demostrar o refutar que es válida la tripla

{Pre Q: a = A ∧ b = B}
program ejemplo_6
 input: a:ℤ, b:ℤ
 if a > b then
   a := a + b
   b := a - b
   a := a - b
 else
   //bloque vacío
 return a, b
{Pos R: ((a = A ∧ b = B) ∨ (a = B ∧ b = A)) ∧ a ≤ b}

Tenemos la tripla
   {a = A ∧ b = B}
     if a > b then
       a := a + b
       b := a - b
       a := a - b
     else
       //bloque vacío
   {Pos R: ((a = A ∧ b = B) ∨ (a = B ∧ b = A)) ∧ a ≤ b}

La precondición más débil del programa con respecto a la poscondición es


(a>b ⇒ wp(a:=a+b ; b:=a-b ; a:=a-b, ((a=A ∧ b=B) ∨ (a=B ∧ b=A)) ∧ a≤b)) ∧
(¬(a>b) ⇒ wp(<vacío>, ((a=A ∧ b=B) ∨ (a=B ∧ b=A)) ∧ a≤b))

En este punto, la expresión es muy larga. Se recomienda extraer fragmentos y evaluarlos separadamente.
Para reducir un poco la expresión, evaluaremos primero
   wp(a:=a+b ; b:=a-b ; a:=a-b, ((a=A ∧ b=B) ∨ (a=B ∧ b=A)) ∧ a≤b)

≡  wp(a:=a+b ; b:=a-b, wp(a:=a-b, ((a=A ∧ b=B) ∨ (a=B ∧ b=A)) ∧ a≤b))

≡  wp(a:=a+b ; b:=a-b, ((a-b=A ∧ b=B) ∨ (a-b=B ∧ b=A)) ∧ a-b≤b)

≡  wp(a:=a+b, wp(b:=a-b, ((a-b=A ∧ b=B) ∨ (a-b=B ∧ b=A)) ∧ a-b≤b))

≡  wp(a:=a+b,((a-(a-b)=A ∧ a-b=B) ∨ (a-(a-b)=B ∧ a-b=A)) ∧ a-(a-b)≤a-b)

≡  (((a+b)-((a+b)-b)=A ∧ (a+b)-b=B) ∨ ((a+b)-((a+b)-b)=B ∧ (a+b)-b=A)) ∧      


   (a+b)-((a+b)-b)≤(a+b)-b

≡  (b=A ∧ a=B) ∨ (b=B ∧ a=A)) ∧ b≤a

POLITÉCNICO GRANCOLOMBIANO 11
Si sustituimos en la precondición más débil del programa original se tiene

(a>b ⇒ ((b=A ∧ a=B) ∨ (b=B ∧ a=A)) ∧ b≤a) ∧


(¬(a>b) ⇒ ((a=A ∧ b=B) ∨ (a=B ∧ b=A)) ∧ a≤b)

Demostraremos ahora la tripla correspondiente al problema inicial

   a=A ∧ b=B ⇒ (a>b ⇒ ((b=A ∧ a=B) ∨ (b=B ∧ a=A)) ∧ b≤a) ∧


                (¬(a>b) ⇒ ((a=A ∧ b=B) ∨ (a=B ∧ b=A)) ∧ a≤b)         ( hip. a=A, b=B )

≡  a=A ∧ b=B ⇒ (a>b ⇒ ((B=A ∧ A=B) ∨ (B=B ∧ A=A)) ∧ b≤a) ∧


                (a≤b ⇒ ((A=A ∧ B=B) ∨ (A=B ∧ B=A)) ∧ a≤b)  

≡  a=A ∧ b=B ⇒ (a>b ⇒ ((B=A ∧ A=B) ∨ true) ∧ b≤a) ∧


                (a≤b ⇒ (true ∨ (A=B ∧ B=A)) ∧ a≤b)       ( elemento absorbente de ∨ )         

≡  a=A ∧ b=B ⇒ (a>b ⇒ true ∧ b≤a) ∧


                (a≤b ⇒ true ∧ a≤b)                                    ( neutro de ∧ )           

≡  a=A ∧ b=B ⇒ (a>b ⇒ b≤a) ∧ (a≤b ⇒ a≤b)                                    

≡  a=A ∧ b=B ⇒ true ∧ true

≡  a=A ∧ b=B ⇒ true

≡  true

Concluimos que el programa es correcto con respecto a su especificación.

POLITÉCNICO GRANCOLOMBIANO 12
3. Resumen
La siguiente tabla recopila las fórmulas para obtener la precondición más débil de programas
construidos a partir de las instrucciones fundamentales de un lenguaje de programación imperativo,
con excepción de los ciclos:

Programa (S) Precondición más débil ( wp(S, R) )


<Instrucción vacío> R
x:=E R(x:=E)
if C then S else S
1 2
((C ⇒ wp(S , R)) ∧ (¬C ⇒ wp(S , R)))
1 1

S   1
wp(S , wp(S , R))
1 2

S 2

S   1
wp(S , wp(S , wp(S , wp(S , … wp(S , R)))))
1 2 3 4 k

S 2

S k

Para demostrar la validez de la tripla {Q}S{R} es suficiente demostrar que [Q ⇒ wp(S, R)].

POLITÉCNICO GRANCOLOMBIANO 13
Referencias
Hoare, C. A. R. (1969). An axiomatic basis for computer programming. Communications of the ACM 12
(10), 576-580. DOI=http://dx.doi.org/10.1145/363235.363259

Kaldewaij, A. (1990). Programming: The Derivation of Algorithms. Upper Saddle River, NJ, USA:
Prentice-Hall, Inc.

POLITÉCNICO GRANCOLOMBIANO 14
INFORMACIÓN TÉCNICA

Módulo: Análisis y Verificación de Algoritmos


Unidad 1: Verificación de programas
Escenario 2: Corrección de programas

Autor: Edwin Andrés Niño


Asesor Pedagógico: Edwin Mojica
Diseñador Gráfico: Andrés Felipe Figueroa
Asistente: Eveling Patricia Peñaranda

Este material pertenece al Politécnico Grancolombiano.


Prohibida su reproducción total o parcial.

POLITÉCNICO GRANCOLOMBIANO 15

También podría gustarte