Corrección de algoritmos

Anuncio
Introducción a la Computación
Primer Cuatrimestre de 2012
Corrección de Algoritmos
1
Especificación, algoritmo y programa
Especificación de un problema:
I
¿Qué problema tenemos?
I
Lenguaje formal (ej. lógica de primer orden).
Algoritmo: Una solución abstracta del problema (escrita para
humanos).
I
¿Cómo resolvemos el problema?
I
Pseudocódigo.
Programa: Una solución concreta del problema (escrita para
computadoras).
I
¿Cómo resuelve la computadora el problema?
I
Lenguaje de programación (ej. C, Python).
2
Especificación de problemas
Una especificación es un contrato con 3 partes:
1. Encabezado
Indica el nombre, el tipo y número de los argumentos, y el
tipo del valor de retorno (RV ).
2. Precondición
Es una condición sobre los argumentos de entrada.
3. Poscondición
Es una descripción del resultado del algoritmo.
Si la entrada es aceptable, el algoritmo debe terminar exitosamente
y la salida debe cumplir las propiedades especificadas.
3
Ejemplo de especificación
Encabezado: sumarPares : A ∈ Z[] → Z
Precondición: {A = A0P
}
Poscondición: {RV = 0≤i<|A0 |∧Par (A0 [i]) A0 [i]}
donde Par (n) ≡ (∃k) n = 2 ∗ k
Obs: Si no se especifica el tipo de una variable, por defecto es Z.
Lo siguiente es pensar un algoritmo que satisfaga esta
especificación. Lo escribimos usando pseudocógido.
4
Pseudocódigo
C
a = b;
if (cond) {..} else {..}
while (cond) {..}
! && ||
== >= <=
return exp;
Pseudocódigo
a←b
if (cond) {..} else {..}
while (cond) {..}
¬ ∧ ∨
= ≥ ≤
RV ← exp
(*)
Declaración local de
variables auxiliares.
Declaración global de
variables auxiliares.
(*) En C, “return exp;” termina la ejecución de la función; en nuestro
pseudocógido, “RV ← exp” es una simple asignación, tras la cual el
algoritmo continúa.
5
Ejemplo de algoritmo en pseudocógido
Encabezado: sumarPares : A ∈ Z[] → Z
Precondición: {A = A0P
}
Poscondición: {RV = 0≤i<|A0 |∧Par (A0 [i]) A0 [i]}
RV ← 0
i ←0
while (i < |A|) {
if (A[i] mod 2 = 0) {
RV ← RV + A[i]
}
i ←i +1
}
¿Cómo sabemos si este
algoritmo es correcto
respecto de la especificación?
donde i ∈ Z.
6
Testing vs. corrección de algoritmos
Dada una especificación E de un problema y un algoritmo A.
Testing de A: Experimentación de la corrida de A para un
conjunto finito de datos de entrada, donde verificamos si cumple
E.
Corrección de A respecto de E : Demostración formal de que el
programa P transforma todos los posibles datos de entrada, en
salidas de acuerdo con E .
7
Corrección de algoritmos
Terna de Hoare
{precondición}
algoritmo
{poscondición}
{P}
S
{Q}
S modifica al estado P, ¿pero lleva a Q?
Una forma de probarlo: Ver que la poscondición más fuerte de
ejecutar S a partir de P, implica Q.
¿sp(S, P) ⇒ Q?
sp(S, P) (strongest postcondition) es el predicado más fuerte
posible como consecuencia de ejecutar S a partir del estado P.
8
Asignación
{P} x ← E {Q}
Queremos probar que sp(x ← E , P) ⇒ Q.
Definición:
sp(x ← E , P) ≡ (∃y ) x = E [x : y ] ∧ P[x : y ]
donde:
I
y es una variable no usada;
I
H[v : E ] es la sustitución de cada instancia en H de la
variable v por la expresión E .
Ejemplo: (x + y )[y : z 2 + 1] = (x + z 2 + 1).
9
Asignación: Ejemplo
Probar la corrección del siguiente algoritmo respecto de su
especificación:
P ≡ {x > 1}
x ←x +1
Q ≡ {x > 2}
sp(x ← x + 1, x > 1) ≡
≡ (∃y ) x = (x + 1)[x : y ] ∧ (x > 1)[x : y ]
≡ (∃y ) x = y + 1 ∧ y > 1
⇒x >2
10
Secuencialización
{P} S1 ;S2 {Q}
Queremos probar que sp(S1 ;S2 , P) ⇒ Q.
Definición:
sp(S1 ;S2 , P) ≡ sp(S2 , sp(S1 , P))
11
Secuencialización: Ejemplo
P ≡ {x > 1}
x ←x +1
y ←2∗x
Q ≡ {y > 4}
sp(x ← x + 1; y ← 2 ∗ x, P) ≡
≡ sp(y ← 2 ∗ x, sp(x ← x + 1, P))
≡ sp(y ← 2 ∗ x, (∃a) x = (x + 1)[x : a] ∧ (x > 1)[x : a])
≡ sp(y ← 2 ∗ x, (∃a) x = a + 1 ∧ a > 1)
≡ (∃b) y = (2 ∗ x)[y : b] ∧ ((∃a) x = a + 1 ∧ a > 1)[y : b]
≡ (∃b) y = 2 ∗ x ∧ (∃a) x = a + 1 ∧ a > 1
≡ y = 2 ∗ x ∧ (∃a) x = a + 1 ∧ a > 1
⇒y =2∗x ∧x >2
⇒y >4
12
Condicional
{P} if (B) S1 else S2 {Q}
Queremos probar que sp(if (B) S1 else S2 , P) ⇒ Q.
Definición:
sp(if (B) S1 else S2 , P) ≡ sp(S1 , B ∧ P) ∨ sp(S2 , ¬B ∧ P)
¿Qué pasa si no hay “else”? Formalmente, if (B) S1 equivale a if
(B) S1 else skip, donde skip es una instrucción especial que no
tiene efecto:
sp(skip, P) ≡ P
Por lo tanto:
sp(if (B) S1 , P) ≡ sp(S1 , B ∧ P) ∨ (¬B ∧ P)
13
Condicional: Ejemplo
P ≡ {a = a0 ∧ b = b0 }
if (a ≤ b) {
RV ← 0
} else {
RV ← a − b
}
Q ≡ {RV = a0 −̇b0 }
donde x −̇y =
0
x −y
si
si
x ≤y
x >y
14
Condicional: Ejemplo
P ≡ {a = a0 ∧ b = b0 }
if (a ≤ b) { RV ← 0 } else { RV ← a − b }
Q ≡ {RV = a0 −̇b0 }
sp(if (a ≤ b){RV ← 0}else{RV ← a − b}, P) ≡
≡ sp(RV ← 0,
a ≤ b ∧ P) ∨
sp(RV ← a − b, a > b ∧ P)
≡ ((∃x) RV = 0[RV : x]
∧(a ≤ b ∧ P)[RV : x]) ∨
((∃y ) RV = (a − b)[RV : y ] ∧(a > b ∧ P)[RV : y ])
≡ ((∃x) RV = 0
∧(a ≤ b ∧ P)) ∨
((∃y ) RV = (a − b) ∧(a > b ∧ P))
≡ (RV = 0
∧(a ≤ b ∧ a = a0 ∧ b = b0 )) ∨
(RV = (a − b) ∧(a > b ∧ a = a0 ∧ b = b0 ))
⇒ RV = a0 −̇b0
15
Repaso de la clase de hoy
I
Pseudocódigo
I
Testing vs. corrección de algoritmos
I
Terna de Hoare; poscondición más fuerte (sp).
I
Asignación, secuencialización, condicional.
Temas de la clase que viene
I
Corrección de ciclos.
16
Descargar