Algoritmos y Estructura de Datos I Ciclos I Lean Viernes 30 de Septiembre de 2016 Hoy nos toca... I Ciclos 101 I Teorema del invariante. ¿Qué era eso? I Definir componentes del ciclo 1 / 13 Estructura del ciclo Sintaxis: while (B) { h cuerpo del ciclo i } I B: expresión booleana del lenguaje de programación. Se la llama guarda. 2 / 13 Estructura del ciclo Sintaxis: while (B) { h cuerpo del ciclo i } I {h cuerpo del ciclo i}: es un bloque de instrucciones entre llaves. I Se repite mientras valga la guarda B. I Puede ejecutarse cero o más veces. I Cada repetición se llama una iteración. 3 / 13 Estructura del ciclo Sintaxis: while (B) { h cuerpo del ciclo i } I La ejecución del ciclo termina si y sólo si el ciclo se repite una cantidad finita de veces. Esto ocurre si y sólo si la guarda B llega a ser falsa. I Si el ciclo termina, el estado resultante es el estado posterior a la última instrucción del cuerpo del ciclo. 4 / 13 Repaso: Teorema del invariante I Necesitamos poder hacer demostraciones en programas que tienen ciclos I Por eso, el teorema del invariante va a ser nuestra herramienta favorita! I ¿Cómo funciona? I Necesitamos una especificación del ciclo Si demostramos la validez de 5 condiciones entonces habremos probado I I I que el ciclo termina que el ciclo es correcto con respecto a su especificación 5 / 13 Teorema del invariante: Especificación I PC (Bool): precondición del ciclo I QC (Bool): postcondición del ciclo I I (Bool): Si vale al comenzar el cuerpo del ciclo, entonces vale después de ejecutar la última instrucción del cuerpo del ciclo I Expresión variante (v ) (Int): Usa variables del programa y tiene que decrecer en cada iteración I Cota (c) (Int): Es un valor que si es alcanzado por la expresión variante, garantiza que la ejecución sale del ciclo 6 / 13 Teorema del invariante: Condiciones I PC → I I (I ∧ ¬B) → QC I El invariante se preserva en la ejecución del cuerpo, i.e. si I ∧ B vale en el primer estado del ciclo entonces I vale en el último I v es decreciente, i.e. v @Eciclo1 > v @EcicloN I (I ∧ v ≤ c) → ¬B 7 / 13 Ejercicios 8 / 13 Máximo problema maximo (a: [Z], n: Z) = res : Z { requiere |a| > 0 ; requiere n == |a| ; asegura res ∈ a ∧ (∀i ← [0..|a|))res ≥ ai ; } int maximo(int a[], int n) { int res = a[0]; int i = 1; while (i < n) { if (a[i] > res) { res = a[i]; } i++; } return res; } 9 / 13 Máximo int maximo(int a[], int n) { int res = ...; int i = ...; while (...) { ... } return res; } Reescribir el código para que el ciclo se corresponda con la siguiente función variante: fv = n/2 + 1 − i (cota: 0). 10 / 13 Duplicar Implementar una función (y especificar su ciclo) que cumpla la siguiente especificación: problema duplicar (a: [Z], n: Z) { requiere n == |a| ; requiere n mod 2 == 0 ; modifica a ; asegura |a| == |pre(a)| ∧ (∀i ← [0.. |a|))ai == 2 ∗ pre(a)i ; } ¿Y si queremos que el ciclo cumpla este invariante? (E es el estado previo al ciclo): I : 0 ≤ i ≤ n/2∧ (∀j ← [0..i))(aj == 2 ∗ a@Ej ∧ aj+n/2 == 2 ∗ a@Ej+n/2 )∧ (∀j ← [i..n/2))(aj == a@Ej ∧ aj+n/2 == a@Ej+n/2 ) 11 / 13 Nuestro viejo y querido Fibo Implementar una función (y especificar su ciclo) que cumpla la siguiente especificación: problema sucesionFibo (a: [Z], n: Z) { requiere n == |a| ; requiere n > 1 ; modifica a ; asegura |a| == |pre(a)| ∧ esSucesionFibo(a, n) ; aux esSucesionFibo (a: [Z], n: Z) : Bool = (∀i ← [0..n)) iesimoFibo(a, i) ; aux iesimoFibo (a: [Z], i: Z) : Bool = if i ≤ 1 then a[i] == 1 else a[i] == a[i − 1] + a[i − 2] ; } 12 / 13