ferramentas de análise

11
ANÁLISE DE ALGORITMOS – AULA 1 Página 1 de 11 FERRAMENTAS DE ANÁLISE 1 INTRODUÇÃO As estruturas de dados e os algoritmos são conceitos centrais para a computação, pois se constituem nas ferramentas básicas para a construção de softwares. De forma simples, uma estrutura de dados é a forma pela qual a informação é organizada e armazenada, e um algoritmo é um procedimento, passo a passo, para realizar alguma tarefa em tempo finito. O quadro-resumo a seguir exibe as etapas na construção de um programa computacional, inserindo as estruturas de dados e os algoritmos no processo de solução de um problema. MODELO MATEMÁTICO TIPOS ABSTRATOS DE DADOS (TAD’s*) ESTRUTURAS DE DADOS ALGORITMO INFORMAL PROGRAMA EM PSEUDOLINGUAGEM PROGRAMA COMPUTACIONAL * TAD é a descrição matemática dos valores que um tipo de dado pode ter e das operações que podem ser feitas com eles. Como se está interessado em bons algoritmos e estruturas de dados, é importante a definição de ferramentas de análise. A ferramenta básica de análise envolve a caracterização do tempo de execução de algoritmos e operações sobre estruturas de dados, com seu consumo de memória também sendo de interesse. 2 TEMPO DE EXECUÇÃO Se um algoritmo for implementado, é possível estudar o tempo gasto por ele executando-o com vários dados de entrada e registrando o tempo gasto em cada execução. Essas medições podem ser feitas de forma precisa usando-se chamadas do sistema que são incluídas na linguagem ou no sistema operacional em que o algoritmo foi implementado. Em geral, o interesse é determinar a dependência do tempo de execução com respeito ao tamanho da entrada fornecida para o algoritmo. Para determiná-la, podem-se realizar vários experimentos e, por meio de gráficos, relacionar o tamanho da entrada com o tempo de execução medido. Para ser significativa, essa análise exige que sejam escolhidos bons

Upload: marco

Post on 21-Dec-2015

214 views

Category:

Documents


0 download

DESCRIPTION

Ferramentas de Análise

TRANSCRIPT

Page 1: Ferramentas de Análise

ANÁLISE DE ALGORITMOS – AULA 1

Página 1 de 11

FERRAMENTAS DE ANÁLISE

1 INTRODUÇÃO

As estruturas de dados e os algoritmos são conceitos centrais para a computação, pois

se constituem nas ferramentas básicas para a construção de softwares. De forma simples, uma

estrutura de dados é a forma pela qual a informação é organizada e armazenada, e um

algoritmo é um procedimento, passo a passo, para realizar alguma tarefa em tempo finito.

O quadro-resumo a seguir exibe as etapas na construção de um programa

computacional, inserindo as estruturas de dados e os algoritmos no processo de solução de

um problema.

MODELO MATEMÁTICO TIPOS ABSTRATOS DE DADOS

(TAD’s*) ESTRUTURAS DE DADOS

ALGORITMO INFORMAL PROGRAMA EM

PSEUDOLINGUAGEM

PROGRAMA

COMPUTACIONAL

∗ TAD é a descrição matemática dos valores que um tipo de dado pode ter e das operações que

podem ser feitas com eles.

Como se está interessado em bons algoritmos e estruturas de dados, é importante a

definição de ferramentas de análise. A ferramenta básica de análise envolve a caracterização

do tempo de execução de algoritmos e operações sobre estruturas de dados, com seu

consumo de memória também sendo de interesse.

2 TEMPO DE EXECUÇÃO

Se um algoritmo for implementado, é possível estudar o tempo gasto por ele

executando-o com vários dados de entrada e registrando o tempo gasto em cada execução.

Essas medições podem ser feitas de forma precisa usando-se chamadas do sistema que são

incluídas na linguagem ou no sistema operacional em que o algoritmo foi implementado.

Em geral, o interesse é determinar a dependência do tempo de execução com respeito

ao tamanho da entrada fornecida para o algoritmo. Para determiná-la, podem-se realizar

vários experimentos e, por meio de gráficos, relacionar o tamanho da entrada com o tempo de

execução medido. Para ser significativa, essa análise exige que sejam escolhidos bons

Page 2: Ferramentas de Análise

ANÁLISE DE ALGORITMOS – AULA 1

Página 2 de 11

exemplos de entradas e que sejam feitos testes suficientes para que se possam fazer

afirmações válidas sob o ponto de vista estatístico.

2.1 Fatores que afetam o tempo de execução

O tempo de execução de um algoritmo depende de uma série de fatores:

• Cresce com o tamanho da entrada, embora possa variar para entradas diferentes,

porém de mesmo tamanho.

• É afetado pelo hardware em que o algoritmo é executado (processador,

freqüência, memória, disco, etc.) e pelo software (sistema operacional, linguagem

de programação, compilador, interpretador, etc.) sobre o qual o algoritmo é

implementado, compilado e executado.

Se todos os outros fatores forem iguais, o tempo de execução do mesmo algoritmo para

os mesmos dados de entrada será menor se o computador tiver, por exemplo, um processador

muito mais rápido, ou se a implementação for feita como um programa escrito em código de

máquina em vez de uma implementação interpretada em uma máquina virtual.

2.2 Requisitos para uma metodologia geral de análise

Embora os estudos experimentais dos tempos de execução sejam úteis, eles têm três

limitações sérias:

• Os experimentos são feitos utilizando-se um número limitado de entradas de

teste, podendo não ser indicativos do tempo de execução com outras entradas

que não foram incluídas nos experimentos.

• É difícil comparar a eficiência de dois algoritmos, a não ser que os experimentos

para a obtenção de seus tempos de execução tenham sido feitos com o mesmo

conjunto de hardware e software.

• É necessário implementar e executar um algoritmo para poder estudar seu tempo

de execução experimentalmente.

Desta forma, é apresentada neste curso uma metodologia geral para analisar o tempo

de execução de um algoritmo, que:

• Leva em conta todas as entradas possíveis.

• Permite avaliar a eficiência relativa de dois algoritmos independentemente do

hardware e do software em que eles são implementados.

• Pode ser feita por meio do estudo de uma descrição de alto nível do algoritmo

(pseudocódigo) sem que seja necessário implementá-lo ou executá-lo.

Page 3: Ferramentas de Análise

ANÁLISE DE ALGORITMOS – AULA 1

Página 3 de 11

Essa metodologia objetiva associar a cada algoritmo uma função f(n) que caracteriza o

tempo de execução do algoritmo como uma função do tamanho n da entrada.

3 ANÁLISE DE ALGORITMOS

3.1 Operações primitivas

Como visto anteriormente, a análise experimental é importante, mas tem suas

limitações. Para analisar um algoritmo em particular sem realizar experimentos para medir seu

tempo de execução, pode-se usar a abordagem analítica. Esta abordagem consiste em analisar

diretamente o código de alto nível ou pseudocódigo.

Para isso, define-se um conjunto de operações primitivas de alto nível que são

independentes da linguagem de programação usada e podem se identificadas no

pseudocódigo. São exemplos de operações primitivas:

• Atribuição de valores a variáveis.

• Chamadas de métodos.

• Operações aritméticas.

• Comparação de dois números.

• Acesso a um arranjo.

• Seguir uma referência a um objeto.

• Retorno de um método.

Uma operação primitiva corresponde a uma instrução de baixo nível com um tempo de

execução constante, mas que depende do ambiente em termos de software e hardware.

Entretanto, nesta abordagem assume-se implicitamente que os tempos de execução de

operações primitivas diferentes são similares. Assim, o número t de operações primitivas que

um algoritmo realiza será proporcional ao tempo de execução desse algoritmo.

Considere-se, como exemplo, o algoritmo seguinte, que retorna o elemento máximo de

um arranjo A de n elementos.

Algoritmo maxVetor (A, n) Entrada: arranjo A com n≥0 elementos Saída: max, o maior elemento em A

max=A[0] % chute inicial para (i=1, i<n, i++) faça

se (A[i]>max) então max=A[i]

retorne (max)

Page 4: Ferramentas de Análise

ANÁLISE DE ALGORITMOS – AULA 1

Página 4 de 11

Número de operações primitivas:

• max=A[0]: duas operações primitivas (indexação de um arranjo e atribuição de

valor a uma variável).

• i=1, no laço: uma operação primitiva (atribuição de valor a uma variável).

• i<n: uma operação primitiva (comparação de dois números) multiplicada por n.

• Corpo do laço, que varia entre 4(n-1) e 6(n-1):

o A[i]>max: duas operações primitivas (indexação de um arranjo e

comparação de dois números).

o max=A[i]: duas operações primitivas (indexação de um arranjo e atribuição

de valor a uma variável), que só serão executadas se o teste anterior for

verdadeiro.

o i++: duas operações primitivas (soma e atribuição de valor a uma variável).

• retorne max: uma operação primitiva.

Resumindo:

• 2 + 1 + n + 4(n-1) + 1 = 5n, no mínimo.

• 2 + 1 + n + 6(n-1) + 1 = 7n – 2, no máximo.

O melhor caso (t(n)=5n) ocorre quando A[0] é o maior elemento e, portanto, a variável

max não tem seu valor alterado posteriormente. O pior caso (t(n)=7n-2) ocorre quando o

arranjo A tem seus elementos em ordem decrescente, de forma que max é alterada a cada

iteração do laço.

3.2 Análise de caso médio, melhor e de pior caso

Um algoritmo pode ser mais rápido para certas entradas do que para outras. Isto

significa que há situações em que o número de operações primitivas é mínimo (melhor caso) e

outras em que este número é máximo (pior caso).

É possível expressar o tempo de execução de um algoritmo como uma média calculada a

partir de todas as entradas possíveis (caso médio). Todavia, uma análise de caso médio requer

tipicamente que sejam calculados os tempos de execução baseados em uma distribuição de

probabilidade. Esse tipo de análise frequentemente exige matemática sofisticada e teoria das

probabilidades.

A figura seguinte exibe esquematicamente como o tempo de execução do caso médio

de um algoritmo pode ter qualquer valor entre o melhor caso e o pior caso, dependendo da

distribuição das entradas.

Page 5: Ferramentas de Análise

ANÁLISE DE ALGORITMOS – AULA 1

Página 5 de 11

A complexidade do pior caso é a mais utilizada porque sua análise é mais fácil do que a

análise do caso médio, já que não requer conhecimento sobre teoria das probabilidades (mas

isso não é uma regra geral). Requer apenas a habilidade de identificar a pior entrada possível,

o que geralmente é simples. Além disso, fornece um limite superior para o número de passos

que o algoritmo pode efetuar, o que pode conduzir a algoritmos melhores: tendo certeza de

que um algoritmo tem bom desempenho no pior caso garante que ele tem bom desempenho

em todos os casos.

4 NOTAÇÃO ASSINTÓTICA

Na análise de algoritmos, é importante concentra-se na taxa de crescimento do tempo

de execução como uma função do tamanho da entrada n, obtendo-se um quadro geral do

comportamento, em vez de concentra-se em detalhes menores. Frequentemente, basta saber

que o tempo de execução de um algoritmo como maxVetor cresce proporcionalmente a n.

Para simplificar a análise, somente o comportamento assintótico é avaliado, desconsiderando-

se constantes aditivas e multiplicativas na expressão matemática obtida.

Desta forma, caracteriza-se o tempo de execução e a quantidade de memória relativos a

um algoritmo usando funções que mapeiam números inteiros em números reais , de forma a

concentrar a atenção no comportamento geral do tempo de execução e da memória exigida.

4.1 Notação O

A notação assintótica foi inventada por P. Bachmann, em 1892, para caracterizar o

comportamento assintótico de funções. Esta notação ficou conhecida como notação O (big oh)

e é definida da seguinte forma:

Page 6: Ferramentas de Análise

ANÁLISE DE ALGORITMOS – AULA 1

Página 6 de 11

Definição: Sejam f(n) e g(n) funções mapeando inteiros não-negativos em números

reais. Dizemos que f(n) é O(g(n)) se existe uma constante real c>0 e uma constante inteira n0≥1

tais que f(n)≤cg(n) para todo inteiro n≥n0.

Esta definição é ilustrada na figura a seguir:

A notação O permite afirmar que uma função de n é assintoticamente “menor que ou

igual a” outra função (pela desigualdade ≤), descontando-se um fator constante (a constante c)

e à medida que n cresce para o infinito (condição n≥0). De outra forma pode-se dizer que a

notação O caracteriza o crescimento assintótico de uma função estabelecendo um limite

superior quanto à taxa de crescimento da função em relação ao crescimento de n.

A notação O é largamente usada para caracterizar o tempo de execução e o consumo de

memória em função de um parâmetro n que varia de problema para problema. A notação O

permite ignorarem-se fatores constantes e termos de menor ordem, centrando-se nos

componentes que mais afetam o crescimento de uma função.

A partir do algoritmo maxVetor, discutido anteriormente, pode-se dizer que o seu

tempo de execução, utilizando a notação assintótica, é O(n). De fato, a partir da expressão 7n-

2, que exprime o número máximo de operações primitivas, a relação f(n)≤cg(n) verifica, ou

seja: 7n-2 ≤ 7n, para c≥7 e para n0≥1.

Exemplos:

• 20n3 + 10n log n + 5 é O(n3). Justificativa: 20n

3 + 10n log n + 5 ≤ 35n3, para c=35 e

n≥1. De fato, qualquer polinômio da forma aknk + ak-1n

k-1 + ... + a0 será sempre

O(nk).

• 3log n + log log n é O(log n). Justificativa: 3log n + log log n ≤ 4log n, para c=4 e n≥2.

• 2100 é O(1). Justificativa: 2100 ≤ 2100, para c=2100 e n≥1.

Page 7: Ferramentas de Análise

ANÁLISE DE ALGORITMOS – AULA 1

Página 7 de 11

4.2 Notações ômega e theta

Da mesma forma que a notação O fornece um limite assintótico superior sobre uma

função, outras notações fornecem maneiras assintóticas de fazer outros tipos de comparações.

Definição: Sejam f(n) e g(n) funções mapeando números inteiros em números reais. Diz-

se que f(n) é Ω(g(n)) (dito f(n) é ômega de g(n)) se g(n) é O(f(n)); ou seja, se existe uma

constante c>0 e uma constante inteira n0≥1 tais que f(n)≥cg(n) para n≥n0.

Esta definição permite dizer que uma função é assintoticamente maior que ou igual a

outra, exceto por um fator constante, conforme ilustra o gráfico seguinte.

Exemplos:

• 20n3 + 10n log n + 5 é Ω(n3). Justificativa: 20n

3 + 10n log n + 5 ≥ 35n3, para c=35 e

n≥1. De fato, qualquer polinômio da forma aknk + ak-1n

k-1 + ... + a0 será sempre

Ω(nk).

• 3log n + log log n é Ω(log n). Justificativa: 3log n + log log n ≥ 3log n, para c=3 e n≥2.

• 7n-2 é Ω(n). Justificativa: se f(n) = 7n-2, a relação 7n-2 ≥ 5n verifica, para c=5 e n0=1

Da mesma que as notações O e Ω, a definição seguinte permite dizer que duas funções

são assintoticamente iguais, exceto por um fator constante.

Definição: Sejam f(n) e g(n) funções mapeando números inteiros em números reais. Diz-

se que f(n) é Ѳ(g(n)) (dito f(n) é theta de g(n)) se f(n) é O(g(n)) e f(n) é Ω(g(n)); ou seja, se

existem constantes c’>0 e c’’>0, e uma constante inteira n0≥1 tais que c’g(n)≤ f(n) ≤ c’’g(n) para

n≥n0.

Exemplos:

• 3log n + log log n é Ѳ(log n). Justificativa: 3log n + log log n ≥ 3log n, para c’’=3 e

n0=2; 3log n + log log n ≤ 4log n, para c’=4 e n0=2.

Page 8: Ferramentas de Análise

ANÁLISE DE ALGORITMOS – AULA 1

Página 8 de 11

5 ANÁLISE ASSINTÓTICA

A tabela seguinte lista as expressões de complexidade mais freqüentes, por ordem de

crescimento assintótico, da direita para a esquerda:

EXPRESSÃO NOME

1 Constante

log Logarítmica

(log ) log quadrado

√ Raiz quadrada

Linear

log n log n

Quadrática

Cúbica

2 Exponencial

Se existem supostamente dois algoritmos diferentes que resolvem o mesmo problema,

um algoritmo A e um algoritmo B, com tempos de execução O(n) e O(n2), respectivamente,

isso implica que o algoritmo A é assintoticamente melhor do que o algoritmo B, embora para

algum dado valor (pequeno) de n seja possível que B tenha um tempo de execução menor do

que o algoritmo A.

A diferença na taxa de crescimento das funções pode ser ilustrada pela tabela seguinte.

Por meio desta tabela é possível perceber a importância da análise de algoritmos para o

projeto de algoritmos.

log √ log 2

2 1 1,4 2 2 4 8 4

4 2 2 4 8 16 64 16

8 3 2,8 8 24 64 512 256

16 4 4 16 64 256 4.096 65.536

32 5 5,7 32 160 1.024 32.768 4.294.967.296

64 6 8 64 384 4.096 262.144 1,84 x 1019

128 7 11 128 896 16.384 2.097.152 3,40 x 1038

256 8 16 256 2.048 65.536 16.777.216 1,15 x 1077

Page 9: Ferramentas de Análise

ANÁLISE DE ALGORITMOS – AULA 1

Página 9 de 11

512 9 23 512 4.608 262.144 134.217.728 1,34 x 10154

1.024 10 32 1.024 10.240 1.048.576 1.073.741.824 1,79 x 10308

5.1 Exemplos de análise assintótica de algoritmos

5.1.1 Algoritmo de tempo quadrático para o problema das médias prefixadas

Algoritmo prefixAverages1 (X) Entrada: arranjo X com n≥1 elementos Saída: arranjo A com n elementos, tal que A[i] é a média de X[0] ... X[i] para (i=0; i<n; i++) faça b=0 para (j=0; j≤i; j++) faça b=b+X[j] A[i]=b/(i+1) retorne (A)

Análise de complexidade de tempo em qualquer caso: O(n2).

5.1.2 Algoritmo de tempo linear para o problema das médias prefixadas

Algoritmo prefixAverages2 (X) Entrada: arranjo X com n≥1 elementos

Saída: arranjo A com n elementos, tal que A[i] é a média de X[0] ... X[i] s=0 para (i=0; i<n; i++) faça s=s+X[i] A[i]=s/(i+1) retorne (A)

Análise de complexidade de tempo em qualquer caso: O(n).

5.1.3 Algoritmo de tempo cúbico para o cálculo do produto matricial

Algoritmo produtoMatricial (A, B) Entrada: arranjos A e B com nXn elementos, n>0 Saída: arranjo C com nXn elementos para (i=0; i<n; i++)faça para (j=0; j<n; j++) faça C[i, j]=0 para (k=0; k<n; k++) faça C[i, j]=A[i, k]*B[k, j]+C[i, j]

Page 10: Ferramentas de Análise

ANÁLISE DE ALGORITMOS – AULA 1

Página 10 de 11

retorne (C)

Análise de complexidade de tempo em qualquer caso: O(n3).

5.1.4 Algoritmo de ordenação por inserção

Algoritmo insertionSort (A) Entrada: arranjo A com n≥1 elementos Saída: arranjo A com n elementos para (j=1; j<n; j++) faça chave=A[j] i=j-1 enquanto (i≥0 e A[i]>chave) faça A[i+1]=A[i] i=i-1 A[i+1]=chave retorne (A)

Análise de complexidade de tempo do pior caso: O(n2).

Análise de complexidade de tempo do melhor caso: O(n).

Análise de complexidade de tempo do caso médio: O(n2).

EXERCÍCIOS

a) Ordene a lista de funções a seguir usando a notação O. Agrupe as funções que são Ѳ uma

da outra.

6 log 2 log log (log ) 2

2 5 , 1 ⁄ 4 ⁄

3, 2 (log ) 2 log

4 √ log 4 log

Dica: quando estiver em dúvida sobre duas funções f(n) e g(n), considere log (f(n)) e log

(g(n)), ou 2f(n) e 2g(n).

b) Faça um gráfico das funções 12, 6 log , , e 2, usando uma escala logarítmica

para os eixos x e y; ou seja, para o valor n e para a função f(n), “plote” a informação no

ponto (log n, log(f(n))).

c) Mostre que (n+1)5 é O(n5).

Page 11: Ferramentas de Análise

ANÁLISE DE ALGORITMOS – AULA 1

Página 11 de 11

d) O algoritmo A usa 10n log n operações enquanto que o algoritmo B usa n2 operações.

Determine o valor para n0 para o qual a é melhor do que B para n≥n0.

e) Mostre que as duas afirmações a seguir são equivalentes:

i. O tempo de execução do algoritmo A é O(f(n)).

ii. No pior caso, o tempo de execução do algoritmo A é O(f(n)).

f) Para cada par de funções f(n) e g(n) na tabela seguinte, indique se f(n)=O(g(n)) (caso 1), ou

se g(n)=O(f(n)) (caso2).

() ()

10 − 10

log

log + log

log √!

ln log

log( + 1) log

2 10

# $

cos( ' 2⁄ ) sin( ' 2⁄ )

( cos )