técnicas de desenho de algoritmos - paginas.fe.up.ptpaginas.fe.up.pt/~prog2/docs/algoritmos.pdf ·...

Post on 10-Feb-2019

263 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Técnicas de Desenho de Algoritmos• Mudança de ênfase:

– da implementação de algoritmos

– para o desenho de algoritmos

• A ver: 5 tipos de algoritmos

– abordagem ao problema

– exemplos

– complexidade em tempo e espaço

Referências:• Mark Allen Weiss. Data Structures & Algorithm Analysis in Java. Addison-

Wesley, 1999. •Robert Sedgewick. Algorithms in C++. Addison-Wesley, 1992. •Steven S. Skiena. The Algorithm Design Manual. Springer 1998.

Algoritmos Gananciosos

• Exemplos Anteriores: Dijkstra, Prim, Kruskal

• Cada fase do algoritmo: – decisão baseada no ganho imediato

– consequências futuras não consideradas

• Algoritmo atinge óptimos locais– se é óptimo global, é solução

– se não, pode servir para obter aproximação

• Exemplo de problema que resolve bem: fazer trocos, minimizando número de notas e moedas

– estratégia: dar repetidamente a maior unidade possível

• Exemplo de problema que não resolve bem: caminho mais rápido usando estratégia da melhor aresta adjacente

Problema de escalonamento

• Dados: tarefas e tempos

• Objectivo: minimizar tempo médio de terminação

TempoTarefa

j 1 15

j 2 8

j 3 3

j 4 10 j3 j2 j4 j1

3 11 21 36

j1 j2 j3 j4

15 23 26 36

Tempo médio: 25

Tempo médio: 17.75

Escalonamento

• 2ª solução é óptima

• Porquê: tarefas mais curtas primeiro

• Tarefas:

• Terminações: ti1, ti1+ti2, ...

• Custo total da solução:

(n ­ k +1) tikk = 1

n∑ (n+1)  tikk =1

n∑ − k tikk = 1

n∑=

Se existe x>y tal que tix < tiy: troca de jix e jiy diminui custo

ji1

, ji2

,..., jin

Escalonamento multiprocessador

• Exemplo com 3 processadores

j1j2j3j4j5j6j7j8j9

356101114151820

Tarefa Tempo

j1

j2

j3

j4

j5

j6

j7

j8

j9

3 5 6 13 16 28 34 4020

Total de tempos: 165Tempo médio: 18.33

Solução óptima não é única

• Para cada i, o≤ i < n/P– as tarefas j iP+1 a j (i+1)P são alocadas a processadores diferentes

j1

j2

j3

j4

j5

j6

j7

j8

j9

3 5 6 14 15 20 30 34 38

Minimizar tempo de completação

• Tempo a minimizar é o da última tarefa a terminar

j1

j2

j3 j4

j5

j6

j7

j8

j9

3 95 14 16 19 34

Este problema é variante do empacotamento, logo NP-completo!

Divisão e conquista

• Divisão: resolver recursivamente problemas mais pequenos (até caso base)

• Conquista: solução do problema original é formada com as soluções dos

subproblemas

– Há divisão quando o algoritmo tem pelo menos 2 chamadas recursivas no corpo

– Subproblemas devem ser disjuntos

• Algoritmos já vistos:

– Travessia de árvores em tempo linear: processar árvore esquerda, visitar nó,

processar árvore direita

– Ordenações:

• mergesort: ordenar 2 subsequências e juntá-las

• quicksort: ordenar elementos menores e maiores que pivot, concatenar

Quicksort

function quicksort(array) var list less, greater if length(array) ≤ 1 return array select and remove a pivot value pivot from array for each x in array if x ≤ pivot then append x to less else append x to greater return concatenate(quicksort(less), pivot, quicksort(greater))

Programação Dinâmica

• Divisão e conquista: problema é partido em subproblemas que se resolvem separadamente; solução obtida por combinação das soluções

• Programação dinâmica: resolvem-se os problemas de pequena dimensão e guardam-se as soluções; solução de um problema é obtida combinando as de problemas de menor dimensão

• Divisão e conquista é top-down

• Programação dinâmica é bottom-up

• Abordagem é usual na Investigação Operacional– “Programação” é aqui usada com o sentido de “formular restrições ao

problema que tornam um método aplicável”

• Quando é aplicável a programação dinâmica: estratégia óptima para resolver um problema continua a ser óptima quando este é subproblema de um problema de maior dimensão

Aplicação directa - Fibonacci

• Problemas expressos recursivamente que podem ser reescritos em formulação iterativa

• Exemplo: números de Fibonacci

/** Números de Fibonacci * versão recursiva */ n >= 0

int fib( const unsigned int n ){

if( n <= 1 )return 1;

else return fib( n-1 ) + fib( n-2 );

}

/** Números de Fibonacci * versão iterativa */int fibonacci(int n ){

int last=1, nextToLast=1, answer=1;if( n <= 1 )

return 1;for( int i = 2; i<=n; i++ ){

answer = last + nextToLast;nextToLast = last;last = answer;

}return answer;

}

Fibonacci

• Expressão recursiva: algoritmo exponencial

• Expressão iterativa: algoritmo linear

Problema na formulação recursiva: repetição de chamadas iguais

F0F1

F2

F3

F4

F5

F6

F1

F2

F0F1

F2

F0

F3

F1

F1 F2

F0

F3

F4

F1

F1

F2

F0F1

Exemplo: Equação de recorrência

C(n) = 2n

C(i)i =0

n−1

∑ + n Para resolver numericamente, expressão recursiva é directa

double eval( int n ){double sum = 0.0;if( n == 0 )return 1.0;

for( int i = 0; i < n; i++ )Sum += eval( i );

return 2.0 * sum / n + n;}

Algoritmo recursivo é exponencial!

Problema: repetição de chamadas

Chamadas Repetidas

C0

C1

C2

C3

C4

C5

C0 C0

C1 C0

C0

C1

C2

C0 C0

C1 C0

C0

C1

C2

C3

C0 C0

C1 C0

C0

C1

C2

C0 C0

C1 C0

Solução iterativa 1

double eval(int n )

{

double [ ] c = new double [n+1];

c[0] = 1.0;

for( int i = 1; i <= n; i++ )

{

double sum = 0.0;

for( int j = 0; j < i; j++ )

sum += c[j];

c[i] = 2.0 * sum / i + i;

}

return c[n];

}

Algoritmo iterativo O(n2)

Evita chamadas recursivas guardando tabela de C(n)

Solução iterativa 2

double eval(int n ){

double sum = 0.0;

double [ ] a = new double [n+1];

a[0] = 1.0;

for( int i = 1; i <= n; i++ )a[i] = a[i-1] + 2.0 * a[i-1] / i + i;

double answer = 2.0 * a[n] / n + n;return answer;

}

Algoritmo iterativo O(n)

Tabela de A(n) guarda valor dos somatórios; para cada entrada basta acrescentar 1 termo

Algoritmos de retrocesso

• Algoritmos em que se geram escolhas que vão sendo testadas e eventualmente refeitas

• Problemas para os quais não existem algoritmos eficientes: retrocesso é melhor que pesquisa exaustiva

– solução é gerada e avaliada parcialmente

– quando uma solução parcial não satisfaz objectivos, retrocesso apenas desfaz última escolha

– evita-se a pesquisa em ramos que garantidamente não levam a solução - poda da árvore de pesquisa

• Exemplo: arranjo da mobília numa casa– grande número de possibilidades

– cada peça de mobília é colocada, solução é arranjo satisfatório

– chegando a ponto onde qualquer arranjo é inconveniente, desfaz-se o último passo e tenta-se alternativa

– muitos arranjos nunca são testados

Problema da portagem

• Dados: n pontos p1, p2, ..., pn situados no eixo dos xx– xi é a coordenada x de pi

– x1= 0

– determinam n (n-1)/2 distâncias d1, d2, ..., dm da forma |xi - xj|

• Distâncias podem ser geradas em tempo O(n2)

Algoritmo que se segue: O(n2 log n) - é conjectura

• Problema inverso: coordenadas dos pontos a partir das distâncias: mais difícil– Não há algoritmo garantido como polinomial para o problema

• D - conjunto das distâncias |D| = m = n (n-1) / 2

Exemplo

D= {1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 10}

|D| = 15 -> n = 6

x1 = 0, x6 = 10

x1 = 0 x6 = 10

D= {1, 2, 2, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8}

maior distância: 8 então x2 = 2 ou x5 = 8 (escolha é indiferente)

x1 = 0 x6 = 10

D= {1, 2, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7}

x5 = 8

Exemplo

7 - maior valor em D -> x4 = 7 ou x2 = 3

x4 = 7 distâncias x6 - 7 = 3 e x5 - 7 = 1 estão em D

x2 = 3 distâncias 3-x1 = 3 e x5 - 3 = 5 estão em D

x1 = 0 x6 = 10x5 = 8x4 = 7

D= {2, 2, 3, 3, 4, 5, 5, 5, 6}

6 - maior valor em D -> x3 = 6 ou x2 = 4

x3 = 6 distância x4 - x3 = 1 impossível, já não existe 1 em D

x2 = 4 distâncias x2-x1 = 4 e x5 - x2 = 4 impossível, só 1 vez 4 em D

É preciso retroceder!

Exemplo

x4 = 7 não conduziu a solução

tenta-se agora x2 = 3

x1 = 0 x6 = 10x5 = 8x2 = 3D= {1, 2, 2, 3, 3, 4, 5, 5, 6}

6 - maior valor em D -> x4 = 6 ou x3 = 4

x3 = 4 impossível, só 1 vez 4 em D

x1 = 0 x6 = 10x5 = 8x2 = 3 x4 = 6

D= {1, 2, 3, 5, 5}

Exemplo

x1 = 0 x6 = 10x5 = 8x2 = 3 x4 = 6x3 = 5

D = { }

x1=0, x5=10

x5=8

x2=3

x3=6 x2=4 x3=4 x4=6

x3=5

x4=7**

* *

Árvore de decisão

Análise

• Na ausência de retrocesso

– D pode ser mantido como árvore de pequisa equilibrada

• O(n2) operações em D

• remoção: D tem O(n2) elementos, não há reinserções, total é O(n2)

• pesquisa: 1 tentativa de colocação faz no máximo 2n, total é O(n2)

– Tempo total é O(n2 log n)

• Com retrocesso: perde-se eficiência

– não existe limite polinomial para o retrocesso requerido

– não estão identificados “exemplos patológicos”

– com pontos de coordenadas inteiras e distribuídas uniformemente, conjectura é que

retrocesso não ocorre mais que O(1)

Jogos

• Como jogar automaticamente um jogo estratégico?

• Exemplo: jogo do galo

– pode construir-se algoritmo que nunca perde e aproveita oportunidades para ganhar

– posições críticas armazenadas em tabela

– escolha de jogada baseada na posição corrente usando uma tabela

– ... todo a análise do jogo feita pelo programador

• Em geral, em jogos não triviais

– não é possível dispor de decisões para todos os caminhos a partir de uma posição

– é preciso recomputar a cada jogada

– é impraticável explorar todas as hipóteses

Minimax

• Estratégia minimax– função de avaliação da “qualidade” de uma posição

• 1 se posição de vitória

• 0 se é empate

• -1 se é para perder

– se se pode fazer avaliação por inspecção do tabuleiro: posição terminal

– posição não terminal: valor é determinado assumindo recursivamente jogadas óptimas de ambos os lados

Um jogador tenta minimizar e o outro maximizar o valor da posição

Para posição P:

• Se é a minha vez de jogar– avalio recursivamente as posições sucessoras Ps, escolhendo o valor maior;

– ao avaliar Ps as suas sucessoras são avaliadas e o menor valor é escolhido (caso mais favorável para o oponente)

Pesquisa com limite de profundidade• Em jogos complexos: inviável pesquisar todos os nós terminais para avaliar a

posição– parar a determinada profundidade

– nós onde pára a recursão tratados como nós terminais

– função de estimativa para avaliar nós terminais

• Ex: xadrez - avaliar peças e suas posições

• Para aumentar o factor de previsão - métodos que avaliam menos nós e não perdem informação sobre posições já avaliadas

X O X X O X...

X OX X O X...

tabela de transposição

Árvore do jogo• Estrutura da pesquisa de posições (nós) e valores das avaliações

42 25 27 7 72 86 9 44 50 68 73 A

42 27 86 44 68 73

27 44 68 C

44 68

44

44

Max

Min

Max

Min

Max

Cortes α −β• Estrutura da pesquisa de posições (nós) e valores das avaliações

73 23 30 40 19 27

73 40 27 B

40 27

40 D

40

44

Max

Min

Max

Min

Max

Corte α

≥ 44

44 ≤ 40

40 D ?

Max

Min

Valor em D não pode aumentar resultado na raiz: o seu nó pai é min e tem valor

garantidamente inferior ao conseguido na raiz até ao momento

Corte β

Valor em C não pode aumentar resultado na raiz: nó pai é max e tem valor

garantidamente superior ao conseguido na raiz até ao momento

≤ 44

44 ≥ 68

68 D ?

Min

Max

top related