Análise de Complexidade

Slides:



Advertisements
Apresentações semelhantes
Projeto de Programação PD-I
Advertisements

AULA 02 PROGRAMAÇÃO LINEAR INTEIRA
Aula T-09 – BCC202 Listas (Parte 1) Túlio Toffolo www. decom. ufop
Programação em Java Prof. Maurício Braga
Analise de Algoritmos e Notação Assintótica
Complexidade de Algoritmos
Exercício Exercício. Considere um algoritmo sequencial que busca um elemento em uma lista não ordenada a) Qual é a complexidade de tempo deste algoritmo.
Aula 10 Algoritmos de Busca
11 de Maio de 2006Listas e Ordenação1 Pedro Barahona DI/FCT/UNL Introdução aos Computadores e à Programação 2º Semestre 2005/2006.
Engenharia de Computação.
Organização e Recuperação da Informação (ORI)
1 Complexidade de Algoritmos Complexidade de pior caso Complexidade de melhor caso de uso bem menos freqüente em algumas situações específicas Complexidade.
Árvores.
1 MergeSort Seja uma lista A de n elementos. O algoritmo consiste das seguintes fases Dividir A em 2 sub-listas de tamanho n/2 Conquistar: ordenar cada.
Pesquisa em Memória Primária
David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP
David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP
Medida do Tempo de Execução de um Programa
David Menotti Estruturas de Dados I DECOM – UFOP
Pesquisa em Memória Primária – Árvores de Busca
Medida do Tempo de Execução de um Programa
Pesquisa em Memória Primária – Árvores de Busca
Medida do Tempo de Execução de um Programa
Medida do Tempo de Execução de um Programa
David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP
Pesquisa em Memória Primária
David Menotti Estruturas de Dados I DECOM – UFOP
Recursividade Conceitos e Aplicações.
Complexidade de Algoritmos
Classificação e Pesquisa de Dados
Dividir-e-Conquistar
Crescimento de Funções
Recorrências.
Complexidade de Computação Para avaliar a qualidade de um algoritmo usamos como critério o espaço e o tempo de execução. Ao.
Programação Dinámica Análise de algoritmos UNISUL
Listas Encadeadas.
Aula T04 – BCC202 Análise de Algoritmos (Parte 2) Túlio Toffolo www
Algoritmos e Estrutura de Dados: Uma pequena motivação
Buscas em Grafos Prof. André Renato 1º Semestre/2012
Paradigmas de programação
Complexidade de Algoritmos
Informática Teórica Engenharia da Computação
Pesquisa em Memória Primária
Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação
Complexidade de algoritmos e Classificação (Ordenação) de dados
Aula 03 – BCC202 Análise de Algoritmos (Parte 1) Túlio Toffolo www
Aula T06 – BCC202 Análise de Algoritmos (Parte 4) Túlio Toffolo
Algoritmos 1º Semestre Materia: Informática Profº: Cristiano.
Introdução e Busca Cega
Mergesort Katia Guimarães.
Campus de Caraguatatuba Aula 12: Sistemas de Equações Lineares (2)
Pesquisa Sequencial e Binária
Campus de Caraguatatuba Licenciatura em Matemática Semestre de 2013
QuickSort Dividir: A[p…r] é particionado (reorganizado) em dois subvetores não vazios A[p…q] e A[q+1…r] tal que cada elemento de A[p…q] é menor ou igual.
Introdução à complexidade de algoritmos Luiz Gonzaga da Silveira Junior.
Aula 10 Algoritmos de Busca
Capítulo VI – Variáveis Indexadas 6.1 – A necessidade de variáveis indexadas 6.2 – Vetores e matrizes 6.3 – Aplicações com vetores numéricos 6.4 – Aplicações.
Complexidade em Tempo de um Algoritmo
Tabela Hash Alunos : Gustavo Jorge Zanin nºUSP
Como analisar um algoritmo
Programação Dinâmica.
INE Fundamentos de Matemática Discreta para a Computação
Complexidade de Computação Katia Guimarães. Avaliando a Qualidade de um Algoritmo É preciso ter bem definido –O que é dado de entrada e –O que é esperado.
Analise de Algoritmos e Notação Assintótica
ATAL – Prof. Jorge Figueiredo Ordenação AT AL Análise e Técnicas de Algoritmos Análise de Algoritmos de Ordenação.
Berilhes Borges Garcia Algoritmos Uma ferramenta para resolver um problema de computação bem- especificado (O espírito da computação) Exemplo: ordenação.
Análise e Complexidade de Algoritmos
Técnicas de Análise de Algoritmos Cristiano Arbex Valle Vinicius Fernandes dos Santos
Comportamento Assintótico
Transcrição da apresentação:

Análise de Complexidade Algoritmos Avançados Análise de Complexidade

COMPLEXIDADE DE ALGORITMOS Definição: A Complexidade de um Algoritmo consiste na quantidade de “trabalho” necessária para a sua execução, expressa em função das operações fundamentais, as quais variam de acordo com o algoritmo, e em função do volume de dados

COMPLEXIDADE DE ALGORITMOS Um algoritmo serve para resolver um determinado problema, e todos os problemas têm sempre uma entrada de dados O tamanho dessa entrada (N) tem geralmente efeito direto no tempo de resposta de um algoritmo Dependendo do problema a ser resolvido, já existem algoritmos prontos ou que podem ser adaptados O problema é: qual algoritmo escolher?

COMO COMPARAR DUAS SOLUÇÕES PARA UM MESMO PROBLEMA ? Tomemos duas soluções para localizar um elemento em um vetor: LIN e BIN Temos dois computadores diferentes, A e B, sendo A um Core 2 Duo e B um Celeron. Tamanho (n) Tempo de execução de LIN em A Tempo de execução de BIN em B 16 8 ns 100.000 ns 64 32 ns 150.000 ns 256 128 ns 200.000 ns 1024 512 ns 250.000 ns Qual é a melhor solução? LIN ou BIN ?

COMO COMPARAR DUAS SOLUÇÕES PARA UM MESMO PROBLEMA ? Tamanho (n) Tempo de execução de LIN em A Tempo de execução de BIN em B 16 8 ns 100.000 ns 64 32 ns 150.000 ns 256 128 ns 200.000 ns 1024 512 ns 250.000 ns ... 1.048.576 524.288 ns 500.000 ns 4.194.304 2.097.152 ns 550.000 ns 16.777.216 8.388.608 ns 600.000 ns 63,072 x 1012 31,536 x 1012 ns ou 1 ano 1.375.000 ns ou cerca de 1,4 segundos

COMPLEXIDADE DE ALGORITMOS Pode-se falar de dois tipos de complexidade de algoritmos : Complexidade Espacial: Quantidade de recursos utilizados para resolver o problema; Complexidade Temporal: Quantidade de tempo utilizado. Pode ser vista também como o número de instruções necessárias para resolver um determinado problema; Em ambos os casos, a complexidade é medida de acordo com o tamanho dos dados de entrada (n) Estamos mais interessados em calcular a Complexidade Temporal de um algoritmo!

COMPLEXIDADE DE ALGORITMOS Existem três perspectivas para análise de complexidade: Melhor Caso Caso Médio Pior Caso Nas três perspectivas, a função f(n) retorna a complexidade de um algoritmo com entrada de tamanho n

ANÁLISE DO MELHOR CASO Definido pela letra grega Ω(Ômega) Exprime o menor tempo de execução de um algoritmo para uma entrada de tamanho n É pouco usado, por ter aplicação em poucos casos. Ex.: O algoritmo de pesquisa sequêncial em um vetor tem complexidade f(n) = Ω(1) A análise assume que o número procurado seria o primeiro selecionado na lista. Abordagem otimista!

ANÁLISE DO CASO MÉDIO Definido pela letra grega θ (Theta) Deve-se obter a média dos tempos de execução de todas as entradas de tamanho n, ou baseado em probabilidade de determinada condição ocorrer Ex.: O algoritmo de pesquisa sequêncial em um vetor tem complexidade f(n) = θ(n/2) Em média será necessário visitar n/2 elementos do vetor até encontrar o elemento procurado Melhor aproximação Muito difícil de determinar na maioria dos casos

ANÁLISE DO PIOR CASO Representado pela letra grega O O maiúsculo. Trata-se da letra grega ômicron maiúscula Baseia-se no maior tempo de execução sobre todas as entradas de tamanho n É o método mais fácil de se obter. Ex.: O algoritmo de pesquisa sequêncial em um vetor tem complexidade f(n) = O(n) No pior caso será necessário visitar todos os n elementos do vetor até encontrar o elemento procurado Abordagem pessimista!

A NOTAÇÃO O Tempo (ou espaço) é contabilizado em número de passos do algoritmo (unidade de armazenamento) Análise do algoritmo determina uma função que depende do tamanho da entrada n. 10n3 + 4n -10 à medida que n aumenta, o termo cúbico começa a dominar A constante do termo cúbico tem relativamente a mesma importância que a velocidade da CPU

A NOTAÇÃO O Desprezar constantes aditivas ou multiplicativas Número de passos 3n será aproximado para n Interesse assintótico termos de menor grau podem ser desprezados n2 + n será aproximado para n2 6n3 + 4n - 9 será aproximado para n3

CÁLCULO DA COMPLEXIDADE Foi visto que, para calcular a complexidade de um algoritmo, deve-se analisar o pior caso A análise deve ser feita de acordo com a tabela a seguir Número de Operações Complexidade f(n) O(f(n)) c x f(n) f(n) + f(n) f(n) + g(n) O(max(f(n),g(n)) f(n) x g(n) O(f(n) x g(n))

CÁLCULO DA COMPLEXIDADE: ALGORITMO ITERATIVO void FloidWarshall(int dist[][]) { int i; int j; int k; for ( k = 0; k < n; k++ ) { for ( i = 0; i < n; i++ ) { for ( j = 0; j < n; j++ ) { int a = dist[i][j]; int b = dist[j][k]; int c = dist[k][j]; dist[i][j] = min(a, b + c ); } int min(int a, int b) { if(a < b) return a; return b; 1 + 1 + 1 + n * ( n * ( 1 + 1 + 1 + n * ( n * ( n * ( 1 + 1 + 1 + 3 ) ) ) 3 + n * n * n * 6 3 + 6n3 O(n3) n * ( 1 + 1 + 1 + 3 ) ) ) 1 + 1 + 1

CÁLCULO DA COMPLEXIDADE: ALGORITMO RECURSIVO A questão se complica um pouco quando se trata de algoritmos recursivos Embora não haja um método único para esta avaliação, a complexidade de um algoritmo recursivo é definida em função de componentes como: Complexidade da base Complexidade do núcleo Profundidade da recursão Número de vezes que o procedimento recursivo é invocado Depende do tamanho do problema e da taxa de redução do tamanho do problema É justamente em sua determinação que reside o problema!

CÁLCULO DA COMPLEXIDADE: ALGORITMO RECURSIVO int fatorial( int n ) { if( n == 0 ) { return 1; //Base } else { return n * fatorial( n – 1 ); // Núcleo } A redução se dá de uma em uma unidade, de n até chegar a 0 Logo, a profundidade da recursão é n Tanto o núcleo quando a base executam apenas uma operação A base é executada uma única vez e o núcleo n - 1 vezes Logo, o número de operações executadas é ((n – 1) * 1) + 1, resultando em uma complexidade O(n)

ORDENS DE ALGORITMOS Complexidade Constante Complexidade Linear Complexidade Logarítmica Complexidade Log Linear Complexidade Quadrática Complexidade Cúbica Complexidade Exponencial Complexidade Fatorial

COMPLEXIDADE CONSTANTE - O(1) São os algoritmos onde a complexidade independe do tamanho n de entradas É o único em que as instruções dos algoritmos são executadas um número fixo de vezes if (condição == true) then { realiza alguma operação em tempo constante } else {

COMPLEXIDADE LINEAR – O(N) Uma operação é realizada em cada elemento de entrada, ex.: pesquisa de elementos em uma lista for (i = 0; i < N; i = i + 1 ) { if (condição == true) then { realiza alguma operação em tempo constante } else {

COMPLEXIDADE LOGARÍTMICA - O(LOGN) Ocorre tipicamente em algoritmos que dividem o problema em problemas menores int PesquisaBinaria ( int array[], int chave , int N){ int inf = 0; int sup = N - 1; int meio; while (inf <= sup) { meio = (inf+sup)/2; if (chave == array[meio]) return meio; else if (chave < array[meio]) sup = meio-1; else inf = meio+1; } return -1; // não encontrado

COMPLEXIDADE LOG LINEAR – O(NLOGN) Ocorre tipicamente em algoritmos que dividem o problema em problemas menores, porém juntando posteriormente a solução dos problemas menores void merge(int inicio, int fim) { if (inicio < fim) { int meio = (inicio + fim) / 2; merge(inicio, meio); merge(meio + 1, fim); mesclar(inicio, meio, fim); }

COMPLEXIDADE QUADRÁTICA – O(N²) Itens são processados aos pares, geralmente com um loop dentro do outro void bubbleSort(int[] a) { for (int i = 0; i < a.length-1; i++) { for (int j = 0; j < a.length-1; j++) { if (a[j] > a[j+1]) { swap(a, j, j+1); }

COMPLEXIDADE CÚBICA – O(N³) Itens são processados três a três, geralmente com um loop dentro do outros dois int dist[N][N]; int i, j, k; for ( k = 0; k < N; k++ ) for ( i = 0; i < N; i++ ) for ( j = 0; j < N; j++ ) dist[i][j] = min( dist[i][j], dist[i][k] + dist[k][j] );

COMPLEXIDADE EXPONENCIAL – O(2N) Utilização de “Força Bruta” para encontrar a solução de um problema. A solução geralmente é baseada diretamente no enunciado do problema e nas definições dos conceitos envolvidos Ex.: Utilizando apenas números é possível criar 10n senhas de n dígitos Um algoritmo de força bruta para quebrar uma dessas senhas tem complexidade O(2n)

COMPLEXIDADE FATORIAL – O(N!) Também é baseada na utilização de força bruta para encontrar a solução de um problema Consiste em testar todas as possíveis permutações existentes na solução à procura da solução ótima para o problema Ex.: Problema do Caixeiro Viajante Encontrar a rota mínima para visitar várias cidades sem repetir nenhuma É um problema base para o projeto de microchips, sequênciamento de genôma e muitas outras aplicações Não possui solução exata eficiente (Problema NP) Utilização de heurísticas para aproximar a solução ótima

ORDENS DE COMPLEXIDADE Imagine um computador que leva 1ms para executar uma operação. A tabela abaixo indica o tempo aproximado de execução de um algoritmo com diferentes ordens de complexidades para 3 tamanhos de entrada n O(n) Log(n) nLog(n) O(n2) O(n3) O(2n) O(n!) 16 0.016s 0.004s 0.064s 0.256s 4s 1m5s 663 anos 32 0.032s 0.005s 0.16s 1s 33s 49 dias 1023 sec 512 0.512s 0.009s 4.608s 4m22s 37h 10143 sec ...

LIMITES SUPERIOR E INFERIOR Todas as ordens de complexidade vistas definem o Limite Superior (Upper Bound) dos Algoritmos Qualquer que seja o tamanho da entrada, o tempo de execução crescerá com velocidade igual ou inferior a apontada pela análise de complexidade. Algumas otimizações podem ser feitas para melhorar o limite superior; Existem, porém, os Limites Inferiores (Lower Bound) para certos problemas, que são pontos a partir dos quais não é mais possível otimizar uma solução algorítmica

LIMITES SUPERIOR E INFERIOR Dado um problema de Multiplicação de 2 matrizes N X N. A solução trivial tem complexidade O(n3); Sabemos assim que a complexidade deste problema não deve superar O(n3), uma vez que existe um algoritmo com está ordem complexidade que o resolve; Este limite superior de um algoritmo pode mudar se alguém descobrir um algoritmo melhor.

LIMITES SUPERIOR E INFERIOR Strassen resolveu o problema com uma complexidade de O(nlog 7) Outros pesquisadores melhoraram ainda mais este resultado. Atualmente o melhor resultado é o de Coppersmith e Winograd de O(n2.376). O limite superior de um algoritmo é parecido com o recorde mundial de uma modalidade de atletismo. Ele é estabelecida pelo melhor atleta (algoritmo) do momento. Assim como o recorde mundial, o limite superior pode ser melhorado por um algoritmo (atleta) mais veloz.

LIMITES SUPERIOR E INFERIOR Às vezes é necessário mostrar que, para um dado problema, qualquer que seja o algoritmo a ser usado, requer um certo número mínimo de operações: o Limite Inferior Para o problema de multiplicação de matrizes de ordem n, apenas para ler os elementos das duas matrizes de entrada leva O(n2). Assim uma cota inferior trivial é Ω(n2).

LIMITES SUPERIOR E INFERIOR Na analogia anterior, o limite inferior não dependeria mais do atleta. Seria algum tempo mínimo que a modalidade exige, qualquer que seja o atleta. Um limite inferior trivial para os 100 metros seria o tempo que a velocidade da luz leva para percorrer 100 metros no vácuo. Se um algoritmo tem uma complexidade que é igual ao limite inferior do problema então o algoritmo é ótimo. O algoritmo de CopperSmith e Winograd é de  O(n2.376) mas o limite inferior é de Ω(n²). Portanto não é ótimo. Este limite superior ainda pode ser melhorado