Análise de programas imperativos AMC 2011/12 Paulo Mateus Departamento de Matemática IST 2012 ì Objectivos ì Noção de invariante e variante de um ciclo ì Prova (informal) da correção de algoritmos imperativos ì Algoritmos de ordenação ì Análise da complexidade dos algoritmos de ordenação ì Análise do pior caso ì Análise de caso médio – suposições probabilísticas Invariante ì Invariante na Lógica de Hoare: ì Def (informal): Uma asserção I diz-se um invariante para um ciclo while(G){ corpo } se, quando for verificada no início do ciclo, também é verificada no fim de cada iterada do ciclo. ì Para tornar esta definição rigorosa era necessário definir: ì ì ì ì Estado do programa (valores das variáveis + estado do controlo) Sintaxe da lógica para os invariantes (primeira-ordem com predicados relevantes) Semântica Nesta disciplina opta-se, como é comum na literatura, por utilizar linguagem matemática informal para analisar os algoritmos imperativos. Invariante - factorial #include <stdio.h> /* Exemplo: factorial com contador a decrescer*/ int main() { int i, r, n; scanf(“%d”,&n); r=1; i=n; n /* Invariante r = ∏ k ∧i >= 1 */ k=i } while(i>=2) { r=r*i; i--; } printf(“O factorial de %d é %d.\n”, n, r); return 0; Prop: O programa Exemplo2, se terminar, calcula o factorial. Algoritmo da Inserção void insertionSort(int V[], int n) { int i=1, j, aux; while(i < n){ aux=V[i]; j = i-1; while(j>=0 && V[j] >aux) { V[j+1] = V[j]; j--; } V[j + 1] = aux; i++; } return; } Invariante - Inserção void insertionSort(int V[], int n) { int i=1, j, aux; /* Invariante 1: Os valores V[0]...V[i-1] estão ordenados e i<=n */ while(i < n){ aux=V[i]; j = i-1; /* Invariante 2: Os valores V[j+1],..,V[i]>= aux e j>=-1*/ while(j>=0 && V[j] >aux) { V[j+1] = V[j]; j--; } V[j + 1] = aux; i++; } } return; Prop: A função insertionSort ordena por ordem crescente o vector V. Variante ì Def. Uma relação (A,<) é bem fundada se qualquer subconjunto não vazio B de A tem elemento minimal. ì Def. Um variante de um ciclo while(G){C} e invariante I é um mapa dos estados que satisfazem I para o suporte A de uma relação bem fundada (A,<) cujo valor decresce estritamente em relação a < por cada iterada do ciclo. Variante ì Regra da correção total do cálculo de Hoare Teo: Dado um invariante I, um ciclo while termina sse existe um variante para esse ciclo e I. Def: Um variante diz-se natural se o suporte da relação bemfundada for um subconjunto dos números naturais. Teo: Ciclos while com variantes naturais não são universais no que diz respeito a algoritmos computáveis à Turing. Variante- factorial #include <stdio.h> /* Exemplo: factorial com contador decrescente*/ int main() { int i, r, n; scanf(“%d”,&n); r=1; i=n; /* Variante ({1...n},<) e f: {σ:σ[i]<=n}è{1...n} tq f(σ)=σ[i] while(i>=2) { r=r*i; i--; } printf(“O factorial de %d é %d.\n”, n, r); return 0; } Prop: O programa factorial termina para todo o input. Exer: Encontre variantes para os ciclos do insertionsort. */ Algoritmo da Inserção void insertionSort(int V[], int n) { int i=1, j, aux; while(i < n){ aux=V[i]; j = i-1; while(j>=0 && V[j] >aux) { V[j+1] = V[j]; j--; } V[j + 1] = aux; i++; } return; } Análise no pior caso - inserção void insertionSort(int V[], int n) { int i=1, j, aux; while(i < n){ aux=V[i]; j = i-1; while(j>=0 && V[j] >aux) { V[j+1] = V[j]; j--; } V[j + 1] = aux; i++; } return; } Análise do pior caso: Time(insertionSort(V,n)= # n−1 i−1 & # n−1 & #1 & O %% ∑∑1(( = O % ∑ i ( = O % n(n −1)( = O(n 2 ) $2 ' $ i=1 ' $ i=1 j=0 ' Análise do melhor caso: BTime(insertionSort(V,n)= # n−1 & O % ∑1( = O ( n −1) = O(n) $ i=1 ' Análise no caso médio - inserção ì Para proceder a análise do caso médio é necessário fazer suposições probabilísticas sobre a entrada de dados. ì Diferentes suposições probabilísticas podem levar a diferentes comportamentos médios. ì A análise corresponde a calcular o valor esperado da complexidade temporal tendo em linha de conta a distribuição de probabilidades das entradas Análise no caso médio - inserção void insertionSort(int V[], int n) { int i=1, j, aux; while(i < n){ aux=V[i]; j = i-1; while(j>=0 && V[j] >aux) { V[j+1] = V[j]; j--; } V[j + 1] = aux; i++; } return; } Análise do caso médio: - Assume que no segundo ciclo poderá terminar com j=-1,0,….,i-1 equiprovavelmente. - O segundo ciclo é iterado i i j i = 2 j=0 j=0 i +1 - ATime(insertionsort(V,n))= ∑ j × p( j) = ∑ # n−1 i & # n−1 i & #1 & O % ∑ ( = O % ∑ ( = O % n(n −1)( = O(n 2 ) $4 ' $ i=1 2 ' $ i=1 2 ' Algoritmo Bubblesort void BubbleSort(int V[], int n) { int i=1, j, aux; while(i < n){ j = 0; while(j<n-i) { if(V[j+1] < V[j]) { aux=V[j]; V[j]=V[j+1]; V[j+1]=aux; }; j++; } i++; } return; } Algoritmo Bubblesort void BubbleSort(int V[], int n){ int i=1, j, aux; /* I1: V[n-i+1]...V[n-1] está ordenado e tem os maiores elementos de V e i<=n+1 */ while(i <= n){ j = 0; /* I2: V[j]é o maior valor de V[0]...V[j] de V e j<=n-i*/ while(j<n-i) { if(V[j+1] < V[j]) { aux=V[j]; V[j]=V[j+1]; V[j+1]=aux; } j--; } i++; } } return; Algoritmo Bubblesort void BubbleSort(int V[], int n){ int i=1, j, aux; /* I1: V[n-i+1]...V[n-1] está ordenado e tem os maiores elementos de V e i<=n+1 */ while(i <= n){ j = 0; /* I2: V[j]é o maior valor de V[0]...V[j] de V e j<=n-i*/ while(j<n-i) { if(V[j+1] < V[j]) { aux=V[j]; Pior, melhor e caso médio? V[j]=V[j+1]; O(n^2) V[j+1]=aux; } j--; } i++; } } return; Algoritmo QuickSort void quickSort(int vec[], int left, int right) { int r; if (right > left) { r = partition(vec, left, right); /* pivot */ quickSort(vec, left, r - 1); quickSort(vec, r + 1, right); } } Algoritmo QuickSort int partition(int vec[], int left, int right) { int i, j; i = left; j = left + 1; while( j <= right) { if (vec[j] < vec[left]) { ++i; swap(vec,i,j); } j++; } swap(vec,left, i); return i; } Algoritmo QuickSort void swap(int vec[] a, b) { int tmp; tmp = vec[a]; vec[a] = vec[b]; vec[b] = tmp; } Algoritmo QuickSort void quickSort(int vec[], int left, int right) { int r; if (right > left) { r = partition(vec, left, right); /* pivot */ quickSort(vec, left, r - 1); quickSort(vec, r + 1, right); } } Algoritmo QuickSort Correção por indução! Análise de complexidade por resolução de recurrências?