Análise e Síntese de Algoritmos
Algoritmos Greedy
CLRS, Cap. 16
Resumo
• Algoritmos Greedy:
– Um primeiro exemplo
• Problema de Selecção de Actividades
– Características das abordagens greedy
– Exemplo: Problema da Mochila
– Exemplo: Minimizar Tempo no Sistema
– Um exemplo final: Códigos de Huffman
2003/2004
Análise e Síntese de Algoritmos
2
Técnicas para Síntese de Algoritmos
• Dividir para conquistar
• Programação dinâmica
• Algoritmos greedy
– Estratégia: a cada passo da execução do algoritmo escolher
opção que localmente se afigura como a melhor para
encontrar solução óptima
• Estratégia permite obter solução óptima?
– Exemplos:
• Kruskal, Prim, Dijkstra, etc.
2003/2004
Análise e Síntese de Algoritmos
3
Exemplo: Selecção de Actividades
• Seja S = { 1, 2, …, n } um conjunto de actividades
que pretendem utilizar um dado recurso
– Apenas uma actividade pode utilizar recurso de cada vez
– Actividade i:
• tempo de início: si
• tempo de fim: ti
• execução da actividade durante [si, ti)
– Actividades i e j compatíveis apenas se [si, ti) e [sj, tj) não se
intersectam
• Objectivo: encontrar conjunto máximo de actividades
mutuamente compatíveis
2003/2004
Análise e Síntese de Algoritmos
4
Exemplo (Cont.)
• Admitir que f1 f2 … fn
• Escolha greedy:
– Escolher actividade com o menor tempo de fim
• Porquê?
– Maximizar espaço para restantes actividades serem realizadas
2003/2004
function Selecionar_Actividades_Greedy(s,f)
n = length[s]
A={1}
j=1
for i = 2 to n
if si fj then
A=A{i}
j=i
return A
Análise e Síntese de Algoritmos
5
Exemplo (Cont.)
• Algoritmo encontra soluções de tamanho máximo para
o problema de selecção de actividades
– Existe uma solução óptima que começa com escolha greedy,
i.e. actividade 1
• A: solução óptima que começa em k
• B=A-{k}{1}
• f1 fk
– Actividades em B são mutuamente disjuntas e A = B
– B é também solução óptima !
2003/2004
Análise e Síntese de Algoritmos
6
Exemplo (cont.)
– Após escolha greedy, problema reduz-se a encontrar
solução para actividades compatíveis com actividade 1
• Seja A solução óptima, e que começa em 1
• A’ = A - { 1 } é solução óptima para S’ = { i S : si f1 }
– Caso contrário, existiria uma solução B’ > A’ para S’ que
permitiria obter solução B para S com mais actvidades do
que A; uma contradição !
– Aplicar indução no número de escolhas greedy
• Algoritmo calcula solução óptima !
• Exemplo
2003/2004
Análise e Síntese de Algoritmos
7
Características das Abordagens Greedy
• Propriedade da escolha greedy
– Óptimo (global) para o problema pode ser encontrado
realizando escolhas locais óptimas
• Sub-estrutura óptima
– Solução óptima do problema engloba soluções óptimas para
sub-problemas
2003/2004
Análise e Síntese de Algoritmos
8
Outro Exemplo: Problema da Mochila
• Definição do problema:
–
–
–
–
–
Dados n objectos (1, …, n) e uma mochila
Cada objecto tem um valor vi e um peso wi
É possível transportar fracção xi do objecto: 0 xi 1
Peso transportado pela mochila não pode exceder W
Objectivo:
• maximizar o valor transportado pela mochila e respeitar
a restrição de peso
• Formalização:
n
max
xivi
i 1
n
s.t.
xiw i W
i 1
v i 0, w i 0, 0 x i 1, 1 i n
2003/2004
Análise e Síntese de Algoritmos
9
Exemplo (Cont.)
• Observações:
– Soma do peso dos n objectos deve exceder peso limite W
– Solução óptima tem que encher mochila completamente,
xi w i W
• Caso contrário poderiamos transportar mais fracções,
com mais valor !
• Algoritmo:
Tempo de
execução:
O(n), ou O(n lg n)
2003/2004
function Encher_Mochila_Greedy(v,w,W)
while weight < W
escolher elemento i com vi/wi máximo
if wi + weight W then
xi = 1; weight += wi
else
xi = (W-weight)/ wi; weight = W
Análise e Síntese de Algoritmos
10
Exemplo (Cont.)
• Se objectos forem escolhidos por ordem decrescente
de vi/wi, então algoritmo encontra solução óptima
–
–
–
–
Admitir: v1/w1 … vn/wn
X = (x1, …, xn): solução calculada por algoritmo greedy
Se xi = 1 para todo o i, solução é necessariamente óptima
Caso contrário, seja j menor indíce tal que xj < 1
• Nota:
–
–
–
–
2003/2004
xi = 1, i < j
xi = 0, i > j
Relação de pesos:
Valor da solução é:
ni1 x i w i W
i1 x i v i VX
n
Análise e Síntese de Algoritmos
11
Exemplo (Cont.)
– Y = (y1, …, yn): uma qualquer solução possível
n
• Peso:
i1 y i w i W
n
• Valor:
V Y y i v i
i 1
– Relação X vs. Y:
i1x i y i w i 0
n
– Notar que, VX VY i1x i y i v i i1x i y i w i
n
n
vi
wi
– Seja j menor indíce tal que xj < 1. Casos possíveis:
• i < j, xi = 1, xi - yi 0, enquanto vi/wi vj/wj
Verifica-se
• i > j, xi = 0, xi - yi 0, enquanto vi/wi vj/wj
sempre:
• i = j, vi/wi = vj/wj
xi yi v i w i xi yi v j w j
2003/2004
Análise e Síntese de Algoritmos
12
Exemplo (Cont.)
– Verifica-se,
V X V Y i1 x i y i w i v i w i v j w j i1 x i y i w i 0
n
n
– V(X) é a melhor solução possível entre todas as soluções
possíveis
• Algoritmo calcula solução óptima !
2003/2004
Análise e Síntese de Algoritmos
13
Exemplo: Minimizar Tempo no Sistema
• Dado um servidor com n clientes, com tempo de
serviço conhecido (i.e. cliente i leva tempo ti),
objectivo é minimizar tempo total dispendido no
sistema (pelo total dos n clientes)
min imizar T i1 tempo total dispendido no sistema pelo cliente i
n
• Exemplo
• Solução (greedy):
– Servir clientes por ordem crescente do tempo de serviço
2003/2004
Análise e Síntese de Algoritmos
14
Exemplo (Cont.)
• Algoritmo greedy encontra solução óptima
– P = p1p2…pn, permutação dos inteiros de 1 a n
• Seja si t pi
– E.g. s1 t p1 t 5
– Com clientes servidos pela ordem P, tempo de serviço do
cliente a ser servido na posição i é si
– Tempo total passado no sistema por todos os clientes é:
s1 aparece n vezes,
n
TP k 1 n k 1sk
e sn aparece 1 vez
– Assumir clientes não ordenados por ordem crescente de
tempo de serviço em P
• Então existem a e b, com a < b, e sa > sb
2003/2004
Análise e Síntese de Algoritmos
15
Exemplo (cont.)
– Trocar ordem dos clientes a e b, de modo a obter ordem P’
• Corresponde a P com inteiros pa e pb trocados
TP' (n a 1)sb n b 1s a
n
n k 1sk
k 1
k a,b
– Obtendo-se,
TP TP'
n a 1sa sb n b 1sb sa
b a sa sb 0
– P’ é uma ordem melhor (com menor tempo de serviço)
• Algoritmo calcula solução óptima !
2003/2004
Análise e Síntese de Algoritmos
16
Exemplo: Códigos de Huffman
• Aplicação: compressão de dados
• Exemplo:
– Ficheiro com 100000 caracteres
Frequência
Código Fixo
a
45
000
b
13
001
c
12
010
d
16
011
e
f
9
100
5
101
– Tamanho do ficheiro comprimido: 3x100000 = 300000 bits
– Código de largura variável pode ser melhor do que código com
largura fixa
• Aos caracteres mais frequentes associar códigos de menor
dimensão
2003/2004
Análise e Síntese de Algoritmos
17
Exemplo (Cont.)
• Código de comprimento variável:
Frequência
Código Variável
a
45
0
b
13
101
c
12
100
d
16
111
e
f
9
1101
5
1100
– Número de bits necessário:
• (45*1 + 13*3 + 12*3 + 16*3 + 9*4 + 5*4)*1000 = 224000 bits
• Códigos livres de prefixo:
– Nenhum código é prefixo de outro código
– 001011101
0.0.101.1101
– Código óptimo representado por árvore binária (completa)
2003/2004
Análise e Síntese de Algoritmos
18
Códigos Livres de Prefixo
100
0
Árvore binária completa:
cada nó interno com 2 filhos
1
a:45
55
25
0
c:12
2003/2004
Código óptimo representado
por árvore completa
1
0
30
1
0
b:13
1
14
d:16
0
1
f:5
e:9
Análise e Síntese de Algoritmos
19
Exemplo (Cont.)
• Dada uma árvore T associada a um código livre de
prefixo
– f(c):
– dT(c):
frequência (ocorrências) do caracter c no ficheiro
profundidade da folha c na árvore
BT
f c dT c
cC
Número de bits
necessário para
representar ficheiro
• Código de Huffman: construir árvore T que corresponde
ao código livre de prefixo óptimo
– Começar com |C| folhas (para cada um dos caracteres do
ficheiro) e realizar |C| - 1 operações de junção para obter árvore
final
2003/2004
Análise e Síntese de Algoritmos
20
Exemplo (Cont.)
function Huffman(C)
n = |C|
Q=C
// Constrói fila de prioridade
for i = 1 to n - 1
z = AllocateNode()
x = left[z] = ExtractMin(Q)
y = right[z] = ExtractMin(Q)
f[z] = f[x] + f[y]
Insert(Q, z)
return ExtractMin(Q)
Tempo de execução: O(n lg n)
2003/2004
Análise e Síntese de Algoritmos
21
Exemplo (Cont.)
• Exemplo
• Código de Huffman para alfabeto C:
– Cada caracter cC com frequência f[c]
– x, y caracteres em C com as menores frequências
– Código óptimo para C representado por árvore binária T
2003/2004
Análise e Síntese de Algoritmos
22
Exemplo (Cont.)
• Facto 1: (propriedade da escolha greedy)
– Existe código livre de prefixo para C tal que os códigos para x e
y (com as menores frequências) têm o mesmo comprimento e
diferem apenas no último bit
• T árvore que representa código óptimo
• b e c caracteres são nós folha de maior profundidade em T
• Admitir, f[b] f[c], e f[x] f[y]
• Notar também que, f[x] f[b], e f[y] f[c]
• T’: trocar posições de b e x em T
• T’’: trocar posições de c e y em T’
• B(T) B(T’) B(T’) B(T’’)
(*)
• Mas, T é óptimo B(T’), B(T’’) B(T)
• T’’ é uma árvore óptima !
2003/2004
Análise e Síntese de Algoritmos
23
Exemplo (Cont.)
• (*)
BT BT'
f c dT c f c dT' c
cC
cC
f [ x]dT x f [b]dT b f [ x]dT ' x f [b]dT ' b
f [ x]dT x f [b]dT b f [ x]dT b f [b]dT x
f [b] f [ x]dT b dT x
0
2003/2004
Análise e Síntese de Algoritmos
24
Exemplo (Cont.)
• Facto 2: (subestrutura óptima)
– Sendo z um nó interno de T, e x e y nós folha
– Considerar um caracter z com f[z] = f[x] + f[y]
– Então T’ = T - {x, y} é óptima para C’ = C - {x, y} { z }
• B(T) = B(T’) + f[x] + f[y]
(**)
• Se T’ é não óptimo, então existe T’’ tal que B[T’’] < B[T’]
• Mas z é nó folha também em T’’ (devido a facto 1)
– Adicionando x e y como filhos de z em T’’
– Código livre de prefixo para C com custo:
» B[T’’] + f[x] + f[y] < B[T]
– mas T é óptimo (B[T’’] + f[x] + f[y] B[T]); pelo queT’
também é óptimo
2003/2004
Análise e Síntese de Algoritmos
25
Exemplo (Cont.)
• (**)
f [ x ]dT x f [ y ]dT y
2003/2004
f [ x] f [ y]dT ' z 1
f [ z]dT ' z f [ x ] f [ y ]
Análise e Síntese de Algoritmos
26
Exemplo (Cont.)
• O algoritmo Huffman produz um código livre de
prefixo óptimo
– Ver factos anteriores
• Propriedade da escolha greedy
• Sub-estrutura óptima
2003/2004
Análise e Síntese de Algoritmos
27
Revisão
• Algoritmos greedy
– Características das abordagens greedy
– Exemplos de aplicação
• String Matching
2003/2004
(CLRS, Cap. 32)
Análise e Síntese de Algoritmos
28