E a chuva ... (Livro pedagógico para ser usado na educação infantil e trabal...
Aulas 11-guloso Algoritmos
1. Projeto e Análise de Algoritmos
Algoritmos Gulosos
e Grafos
Universidade Federal do Amazonas
Departamento de Ciência da Computação
2. 2
Algoritmos Gulosos
n Utilizam o mesmo conceito de
subestrutura ótima usado na prog.
Dinâmica.
n Fazem escolhas com base em dados
locais para encontrar boas soluções
n Técnica pode ser usada para obter
resultados aproximados em alguns casos
3. 3
Árvore Espalhada
n Uma árvore espalhada de um grafo G é
um subgrafo de G que
n é uma árvore
n Contém todos os vértices de G
Árvore espalhada de G
4. 4
Árvore espalhada mínima
n Seja G = (V,E) um grafo
conexo e não dirigido
n Seja uma função de custo W:
E → R que atribui um custo
a cada aresta de G
( , )
( ) ( , )
u v T
w T w u v
∈
= ∑
n Árvore Espalhada: Uma árvore que conecta todos
os vértices
n Árvores Espalhada Mínima: árvore espalhada que
minimiza:
5. 5
Sub-estrutura ótima
n AEM T
n A remoção de algum arco (u,v) particiona T em
T1 e T2
n Como
n T1 é uma AEM de G1=(V1,E1)
n T2 é uma AEM de G2=(V2,E2)
1 2( ) ( , ) ( ) ( )w T w u v w T w T= + +
T1
T2
6. 6
Escolha Gulosa
n Propriedade:
n Escolhas localmente ótimas ou gulosas
(greedy) levam á uma solução global ótima
n Teorema
n Seja G=(V, E), e seja S ⊆ V
n Seja (u,v) a aresta de menor custo em G que
conecta S a V – S
n Então (u,v) ∈ a alguma AEM de G
8. 8
Escolha Gulosa (3)
n Prova
n Suponha (u,v) ∉ T
n Mesmo assim, u e v devem estar em T e deve haver
um caminho de u até v emT
n Seja qualquer aresta (x, y) neste caminho que cruza
de S paraV – S
n Como (u,v) tem o menor custo, então w(u,v) ≤ w(x,y)
n Assim, a árvore que inclui (x,y) não pode ter o custo
menor que árvore que inclui (u,v) e portanto ela não
é mínima.
9. 9
Algoritmo Genérico para AEM
AEM(G,w)
1 A←∅ // Conterá os arcos da AEM
2 enquanto A não formar uma AEM faça
3 Encontre um arco (u,v) seguro para A
4 A←A∪{(u,v)}
5 retorne A
Arco seguro – arco que garante que A:
n forma uma árvore
n inclui os arcos mínimos
10. 10
Alg. Genérico para AEM (2)
AEM2(G, w)
1 A←∅ // Conterá as arestas da AEM
2 enquanto A não for uma árvore espalhada faça
3.1 Faça um corte(S, V-S) em G que respeita A
3.2 Seja (u,v) a aresta mínima entre S e V-S
4 A←A∪{(u,v)}
5 retorne A
11. 11
Algoritmo de Prim
n Algoritmo baseado em vértices
n Constrói uma árvore T, com um vértice de cada
vez.
n Utiliza um conjunto de vértices que corresponde
a porção de T que já foi computada
n Rotula os vertices que estão fora deste
conjunto com
n key[v] – arco de menor custo que conecta v a um
vértice no conjunto
n key[v] = ∞, se não existe tal arco
12. 12
Algoritmo de Prim (2)
Prim(G,w,r)
01 Q ← V[G] // Q – vertices que formarão T
02 para cada u ∈ Q
03 key[u] ← ∞
04 key[r] ← 0
05 π[r] ← NIL
06 enquanto Q ≠ ∅ faça
07 u ← ExtráiMin(Q)
08 para cada v ∈ Adj[u] do
09 se v ∈ Q e w(u,v) < key[v] então
10 π[v] ← u
11 key[v] ← w(u,v)
13. 13
Prim(G,w,r)
01 Q ← V[G] // Q – vertices que formarão T
02 para cada u ∈ Q
03 key[u] ← ∞
04 key[r] ← 0
05 π[r] ← NIL
06 enquanto Q ≠ ∅ faça
07 u ← ExtráiMin(Q)
08 para cada v ∈ Adj[u] do
09 se v ∈ Q e w(u,v) < key[v] então
10 π[v] ← u
11 key[v] ← w(u,v)
Algoritmo de Prim (3)
Atualiza
key[v]
14. 14
O(V) vezes
O(E) arestas
O(log V)
Algoritmo de Prim (4)
O(V)
O(log V)
O(1)
Prim(G,w,r)
01 Q ← V[G] // Q – vertices que formarão T
02 para cada u ∈ Q
03 key[u] ← ∞
04 key[r] ← 0
05 π[r] ← NIL
06 enquanto Q ≠ ∅ faça
07 u ← ExtráiMin(Q)
08 para cada v ∈ Adj[u] do
09 se v ∈ Q e w(u,v) < key[v] então
10 π[v] ← u
11 key[v] ← w(u,v)
18. 18
Filas de Prioridade
n Uma fila de prioridades (FP) é uma ED que
mantém um conjunto S de elementos, cada um
associado a uma chave (key).
n Uma FP deve suportar as seguintes operações:
n ConstróiFP(S): Carrega a FP com os elementos de S
n ExtráiMin(S): retorna e remove o elemento de S que
tem a menor chave
n Atualiza(S,x,novachave): muda a chave do elemento
x
n Um heap binário pode ser usado
n ConstróiFP – O(n)
n ExtraíMin e Atualiza – O(lg n)
19. 19
Prim: Tempo de Execução
n |V |.T (ExtráiMin) + O (E ).T (Atualiza)
n O (V lgV + E lgV) = O (E lgV )
Fila T(ExtráiMin) T(Atualiza) Total
array O (V ) O (1) O(V 2)
Heap binário O (lg V) O(lg V) O(E lgV )
Heap de Fibonacci O(lg V) O(1) O(V lgV +E )
20. 20
Algoritmo de Kruskal
n Algoritmo baseado em arcos
n Adiciona um arco de cada vez na ordem
crescente dos custos
n Mantém uma floresta A.
n Um arco é incluído se ele conecta vértices
de árvores distintas de A.
21. 21
Algoritmo de Kruskal (2)
Kruskal(G,w) /* G=(V,E) */
01 A ← ∅
02 para cada vértice v ∈ V[G] do
03 Constrói-Conjunto({v})
04 Ordenar as arestas de acordo com o custo w
05 para cada arco (u,v) nesta ordem faça
06 se Conjunto_de(u) ≠ Conjunto_de(v) então
07 A ← A ∪ {(u,v)}
08 União(Conjunto_de(u),Conjunto_de(v))
09 retorne A
26. 26
Implementação de Conjuntos
n Para implementar Kruskall é necessário
utilizar uma lista de dados para manter
conjuntos disjuntos de vértices
n Operações
n Constrói_Conjunto(x): S ← {x}
n União(Si,Sj): S ← S – {Si,Sj} ∪ {Si ∪ Sj}
n Conjunto_de(x): retorna Si, tal que x ∈ Si
27. 27
Conjuntos disjuntos como listas
n Cada conjunto – lista de elementos identificados pelo
primeiro elemento.
n Todos os elementos na lista apontam para o primeiro
elemento
n União – adiciona a lista menor à lista maior
n Conjunto-de: O(1), União(u,v): O(min{|C(u)|, C(v)})
1 2 3 A B C
∅
4
∅
1 2 3 A B C
∅
4
28. 28
Kruskal: Tempo de Execução
n Inicialização: O(V)
n Θ(E lg E) ~ Θ(E lg V)
n O(E) chamadas para Conjunto_De
n Custo de uniões
n Seja t(v) o número de vezes em que um vértice v é
movido para um novo conjunto maior
n Cada vez que é um vértice é movido, o novo
conjunto tem seu tamanho pelo menos dobrado: t(v)
≤ log V
n Tempo total de união
n Tempo total: O(E lg V)
( ) log
v V
t v V V
∈
≤∑
30. 30
Caminho Mínimo
n Seja um digrafo (grafo dirigido) G = (V,E) com
uma função de custo W: E → R
n O custo do caminho p = v1 → v2 → … → vk é
n Caminho mínimo: caminho de menor custo
1
1
1
( ) ( , )
k
i i
i
w p w v v
−
+
=
= ∑
31. 31
Caminhos Mínimos
n Problemas de caminho mínimo
n Fonte Única (Destino Único). Encontrar o
caminho mínimo de um dado vértice (fonte) para
todos os outros vértices.
n Par Único. Dados dois vértices, achar o menor
caminho entre eles. A solução para o problema de
fonte única serve para este problema.
n Todos os Pares. Encontrar o caminho mínimo entre
todos os pares de vértices do grafo. Aplica-se
programação dinâmica.
32. 32
Sub-estrutura ótima
n Teorema: os sub-caminhos de um
caminho mínimo são caminhos mínimos
n Prova (cut and paste)
n Se algum sub-caminho não fosse mínimo, ele
poderia ser substituído por um menor que
levaria ao caminho mínimo total.
33. 33
Inequação de triângulos
n Definição
n δ(u,v) ≡ custo cam. min. entre u-v
n Teorema
n δ(u,v) ≤ δ(u,x) + δ(x,v) para qq x
n Prova
n o cam. min. entre u-v não pode ser maior que
nenhum outro caminho entre u-v, em particular o
caminho que concatena os caminhos mínimos entre
u-x e x-v
34. 34
Pesos negativos e ciclos
n Em geral, caminhos mínimos não podem ter
ciclos, pois se tivessem os custo poderia ser
reduzido removendo o ciclo.
n Qualquer caminho mínimo em um grafo não
pode ter mais que n – 1 arestas, onde n é o nr.
de vértices
n Arestas com pesos negativos podem ser
consideradas no caminho mínimo, no entanto,
neste caso, ciclos poderiam levar a caminhos de
custo arbitrariamente menores
35. 35
Relaxamento
n Para cada vértice no grafo, é mantido um valor
d[v], uma estimativa do peso total do camin.
Este valor é inicializado como ∞
n Relaxar um arco (u,v) consiste em testar se é
possível melhorar o caminho corrente para v
passando por u
5
u v
vu
2
2
9
5
7
Relax(u,v)
5
u v
vu
2
2
6
5
6
Relax(u,v)
Relax (u,v,w)
if d[v]>d[u]+w(u,v)then
d[v] ← d[u]+w(u,v)
π[v] ← u
36. 36
Algoritmo de Dijkstra
n Arestas com pesos não negativos
n Algoritmo guloso similar à busca em largura
n Usa uma fila de prioridade Q usando d [v] como
chave
n Idéia básica
n Mantêm um conjunto S de vértices já processados
n A cada passo, seleciona o vértice u mais próximo,
inclui o vértice u, adiciona-o a S e relaxa todos os
arcos que saem de u.
37. 37
Dijkstra(G,w,s)
01 para cada v ∈ V
02 d[v] ← ∞
03 d[s]← 0
04 S ← ∅
05 Q ← V
06 enquanto Q ≠ ∅ faça
07 u ← ExtráiMin(Q)
08 S ← S ∪ {u}
09 para cada v ∈ Adj[u] faça
10 se d[v] > d[u]+w(u,v) então
11 d[v] ← d[u]+w(u,v)
Dijkstra Q : Fila de Prioridade que contém
os vértices e tem d[v] como chave
Q = {(v1,d[v1]), (v2,d[v2]),..., (vV,d[vV])}
Retira o u de menor d[u] de Q
Conjunto de vértices já processados
Relaxamento
38. 38
Dijkstra: Exemplo
∞
∞
∞
∞
0
s
u v
yx
10
5
1
2 3
9
4 6
7
2
10
∞
5
∞
0
s
u v
yx
10
5
1
2 3
9
4 6
7
2
u v
8
14
5
7
0
s
yx
10
5
1
2 3
9
4 6
7
2
8
13
5
7
0
s
u v
yx
10
5
1
2 3
9
4 6
7
2
40. 40
Dijkstra: Corretude
n Provar que sempre que u é adicionado a S
temos d [u] = δ(s,u), ou seja, d é mínimo, e
que isto se mantêm daí em diante
n Prova
n Temos que: ∀v, d [v] ≥ δ(s,v)
n Seja u o primeiro vértice escolhido tal que existe um
caminho mais curto até u ou seja d[u] > δ(s,u)
n Mostraremos que isso leva a uma contradição
41. 41
Dijkstra: Corretude (2)
n Seja y o primeiro vértice em V – S que pertence
ao caminho mínimo verdadeiro de s até u.
n Então d [y] = δ(s,y), pois:
n Para o predecessor x de y, onde x ∈S , d [x] é
mínimo, já que u é o primeiro vértice incorreto
n Além disso, quando x é inserido em S, a aresta (x,y)
foi relaxada, assinalando a d[y] o valor correto.
42. 42
Dijkstra: Corretude (3)
Primeiro vértice
escolhido tal que
d[u] não é mínimo
Vértice que está no
caminho mínimo
“real” até u
Vértice
corretamente
escolhido
43. 43
Dijkstra: Corretude (4)
n Assim:
n d[u] > δ(s,u) * Hipótese inicial
n > δ(s,y)+δ(y,u) * Sub-estrutura ótima
n > d [y]+δ(y,u) * Corretude de d [y]
n d[u] > d [y] * Pesos não negativos
n Mas se d [u] > d [y] o algoritmo teria escolhido
y ao invés de u da fila Q ⇒ contradição
n Portanto d[u] = δ(s,u) no momento da inserção
de u em S.
44. 44
Dijkstra: Tempo de Execução
O(V)
O(V)
O(E) arestas
O(V) vezes
O(log V)
O(log V)
Dijkstra(G,w,s)
01 para cada v ∈ V
02 d[v] ← ∞
03 d[s]← 0
04 S ← ∅
05 Q ← V
06 enquanto Q ≠ ∅ faça
07 u ← ExtráiMin(Q)
08 S ← S ∪ {u}
09 para cada v ∈ Adj[u] faça
10 se d[v] > d[u]+w(u,v) então
11 d[v] ← d[u]+w(u,v)
45. 45
Dijkstra: Tempo de Execução
n Extract-Min: tempo |V |
n Decrementos de chaves: tempo |E |
n Time = |V | TExtract-Min + |E | Tdecrementa-chave
n Depende da implementação
Q T(Extract-Min) T(Decrease-Key)
array Ο(V) Ο(1) Ο(V 2)
binary heap Ο(lg V) Ο(lg V) Ο(E lg V)
Fibonacci
heap
Ο(lg V) Ο(1) Ο(V lgV + E)
46. 46
Algoritmo de Bellman-Ford
n Dijkstra não funciona com arestas
negativas
n Não se pode assumir que o custo dos
caminhos só podem aumentar.
n O Algortimo de Bellman-Ford detecta
ciclos negativos ou retorna os caminhos
mínimos.
47. 47
Bellman-Ford
Bellman-Ford(G,w,s)
01 para cada v ∈ V[G]
02 d[v] ← ∞
03 d[s] ← 0
04 π[r] ← NIL
05 para i ← 1 até |V[G]|-1 faça
06 para cada aresta (u,v) ∈ E[G] faça
07 Relax (u,v,w)
08 para cada vértice (u,v) ∈ E[G] faça
09 se d[v] > d[u] + w(u,v) então retorne falso
10 retorne verdadeiro
50. 50
Bellman-Ford: Tempo
Bellman-Ford(G,w,s)
01 para cada v ∈ V[G]
02 d[v] ← ∞
03 d[s] ← 0
04 π[r] ← NIL
05 para i ← 1 até |V[G]|-1 faça
06 para cada aresta (u,v) ∈ E[G] faça
07 Relax (u,v,w)
08 para cada vértice (u,v) ∈ E[G] faça
09 se d[v] > d[u] + w(u,v) então retorne falso
10 retorne verdadeiro
(|V|-1)|E| + |E| = Θ(VE)
51. 51
Bellman-Ford: Corretude
n Provar que se o menor caminho entre s e
u tem i arestas, então depois do i-ésimo
passo do algoritmo teremos o menor
caminho, ou seja, d[u]=δ(s,u)
n Seja δi(s,u) o custo do caminho de s até u
que é o mínimo entre todos os caminhos
que contém no máximo i arestas
52. 52
Bellman-Ford: Corretude (2)
n Provar por indução que d[u]= δi(s,u)
depois da i-ésima iteração
n Base da indução. Inicio do algoritmo
n Hipótese da indução: d[u] = δi-1(s,u)
n Passo indutivo
n Caso 1: δi(s,u) = δi-1(s,u) => d[u]= δi(s,u)
n Caso 2: δi(s,u) = δi-1(s,z) + w(z,u)
n Na iteração cada arco é relaxado, inclusive (z,u), então
d[u] = δi(s,u)
53. 53
Belman-Ford: Corretude (3)
n Se |V|=n, temos que depois de n-1 iterações:
d[u] = δn-1(s,u), para cada vértice u.
n Se ainda existe alguma aresta a relaxar no grafo
então ainda existe um vértice u tal que δn(s,u) <
δn-1(s,u).
n Mas só existem n vértices. Portanto deve haver
um ciclo, ele deve ser negativo.
n Caso contrário, d[u]= δn-1(s,u) = δ(s,u), para
todo u, uma vez que qualquer caminho mínimo
terá nó máximo n-1 arestas.