Escolar Documentos
Profissional Documentos
Cultura Documentos
naldi@dc.ufscar.br
Agradecimentos
●
Aos professores Mário Felice e Diego Furtado por ceder
parte do material utilizado.
●
Material inspirado nas aulas do prof. Tim Roughgarden
Busca Local
●
É uma técnica abrangente para obter e/ou melhorar
soluções para problemas NP-Completos e NP-
Difíceis
●
Dado um conjunto de soluções candidatas X
●
Definimos o conceito de vizinhança
– baseado em um tipo específico de operação, que
chamaremos operação de vizinhança
●
Duas soluções x e y são vizinhas <--> x pode ser
transformado em y realizando uma operação de
vizinhança, e vice-versa
Exemplo
●
Tomemos o TSP
– Uma solução candidata é um circuito que visita cada vértice
exatamente uma vez
– A operação de vizinhança consiste na troca de duas arestas
quaisquer do circuito
●
De modo que o resultado ainda seja um circuito (veja
exemplo)
●
Assim, dada uma solução candidata para o TSP (um circuito C)
– todo circuito que pode ser obtido através da troca de duas
arestas de C
●
ou seja, que difere de C em exatamente duas arestas,
●
está na vizinhança de C
Algoritmo genérico de busca local
buscaLocal( ){
seja x = uma solução inicial qualquer
enquanto x tiver uma solução vizinha y que é
melhor
x := y
devolva x
}
Busca local
●
Observe que a solução devolvida corresponde a
– um ótimo local com relação ao espaço de busca
definido pela operação de vizinhança
– daí o nome, busca local
Questões Avançadas de Busca Local
●
Entrada
– um grafo G=(V, E)
●
Solução
– um corte (A, B), ou seja, uma partição de V em
dois conjuntos que
●
maximiza o número de arestas com uma ponta
em cada conjunto (arestas cruzando o corte)
Problema do Corte Máximo
●
O problema do Corte Máximo é NP-Difícil
●
Um caso particular tratável deste problema que vale
a pena destacar
– São os grafos bipartidos
●
Ou seja, grafos cujos vértices podem ser
divididos em dois conjuntos disjuntos U e V tais
que toda aresta conecta um vértice em U a um
vértice em V
●
Nestes grafos o problema pode ser resolvido usando
Busca em Largura
Problema do Corte Máximo
●
Para entender o motivo, observe que
– Identificar se um grafo é bipartido pode ser feito
em tempo polinomial
●
Usando justamente o algoritmo de Busca em
Largura
– Como um grafo bipartido é composto por dois
conjuntos independentes, i.e., que não tem
arestas entre si
●
O corte ótimo será formado justamente por
esses dois conjuntos
Problema do Corte Máximo
●
Antes de apresentar um algoritmo de busca local,
vamos definir alguns conceitos
– Dado um corte (A, B) e um vértice v, temos
● cv(A, B) = # arestas incidentes em v que
cruzam o corte (A, B)
● d (A, B) = # arestas incidentes em v que não
v
cruzam o corte (A, B)
●
veja exemplo
●
Dizemos que duas soluções são vizinhas se elas
diferem pela posição de apenas um vértice
Algoritmo de Busca Local
buscaLocalMaxCut(G=(V,E)) {
seja (A, B) um corte arbitrário
enquanto existir um vértice v tal que cv(A, B) < dv(A, B)
troque o conjunto ao qual v pertence no corte (A, B)
devolva (A, B)
}
– Observe que em cada iteração o número de arestas no
corte aumenta de
● dv(A, B) - cv(A, B) > 0
Eficiência
●
Como em cada iteração o corte aumenta de pelo
menos uma aresta
– E o corte máximo não pode ter mais que (n choose
2) = n(n-1)/2 = O(n2) arestas
●
O algoritmo executa em O(n2) iterações
●
Cada iteração leva O(n + m) passos,
– Já que pode precisar verificar todos os vértices para
encontrar aquele que vale a pena trocar de lado
●e para contabilizar cv(A, B) e dv(A, B) precisa
verificar as arestas que saem do vértice v
●
Portanto, o algoritmo é O(m n2)
Eficiência
●
Mas algumas melhorias podem ser feitas para torná-lo
assintoticamente mais eficiente,
– Em particular, podemos pré-calcular os valores de c v e
dv para todo v no início, gastando O(n + m) = O(n 2)
●
Em cada iteração, buscamos por algum vértice com
cv < dv em tempo O(n), no total das iterações
gastando O(n3)
– Após a escolha do vértice em cada iteração, só
alterarmos os valores de cv e dv dos vizinhos do vértice
escolhido. Como um vértice tem no máximo O(n)
vizinhos, ao longo de todas as iterações isso custa no
máximo O(n3)
●
Portanto, seria implementado com eficiência O(n 3)
Garantia de qualidade
●
O algoritmo sempre encontra um corte com pelo
menos 50% das arestas do ótimo.
●
Demonstração:
– Considere um corte (A, B) devolvido pelo algoritmo
– Temos que, para todo vértice v
● cv(A, B) >= dv(A, B)
– Somando sobre todos os vértices temos
∑ c v ( A , B)≥ ∑ d v ( A , B)
v ∈V v ∈V
Garantia de qualidade
●
Ou seja,
– 2 * [# arestas cruzando o corte] >= 2 * [# arestas
que não cruzam o corte]
– Os fatores 2 aparecem porque tanto as arestas
cruzando quanto as não cruzando são contadas
duas vezes nos somatórios anteriores
●
Já que cada uma tem extremos em dois vértices
e os somatórios são sobre os vértices
Garantia de qualidade
●
Para comparar com o número de arestas no corte (A,
B) com o total de arestas do grafo,
– basta dividir os dois lados da inequação por 2
– e somar o [# arestas cruzando o corte]
●
já que |E| = [# arestas que não cruzam o corte] +
[# arestas cruzando o corte]
– [# arestas cruzando o corte] + [# arestas cruzando
o corte] >= [# arestas que não cruzam o corte] + [#
arestas cruzando o corte]
– 2 * [# arestas cruzando o corte] >= |E|
Garantia de qualidade
●
Como o número de arestas no corte máximo
OPT <= |E|, temos
– [# arestas cruzando o corte] >= |E| / 2
●
Portanto, o algoritmo de busca local obtém uma
solução 1/2-aproximada
Algoritmo Aleatorizado
●
Trata-se de um algoritmo muito simples que sorteia
com probabilidade uniforme em que conjunto (A ou
B) vai colocar cada vértice
●
Eficiência: Θ(n)
●
Qualidade da Solução: Exp[# arestas cruzando o
corte] = |E|/2
Algoritmo Aleatorizado
●
Demonstração:
●
Considere um corte (A, B) gerado aleatoriamente
●
Para cada aresta e = (u, v) definimos uma variável
indicadora
– Xe = 1 se e cruza o corte e Xe = 0 caso contrário
●
Observe que
– Exp[Xe] = Prob[Xe = 1] = 1/2
Algoritmo Aleatorizado
●
Pois e = (u, v) cruza o corte
– se u está em A (prob. 1/2) e v está em B (prob.
1/2) → 1/2 * 1/2 = 1/4
●
ou v está em A (prob. 1/2) e u está em B (prob.
1/2) → 1/2 * 1/2 = 1/4
●
probabilidade total = 1/4 + 1/4 = 1/2
Algoritmo Aleatorizado
●
Número esperado de arestas no corte (A, B) é
– Exp[# arestas cruzando o corte] = exp [ ∑ Xe]
e∈E
– pela linearidade da esperança = ∑ exp [ Xe]
e ∈E
=
∑ 1/2
e ∈E
– = |E|/2
Algoritmo Guloso
●
Também podemos pensar num algoritmo guloso que
percorre os vértices numa ordem arbitrária,
– alocando cada vértice em A ou B de modo a
maximizar o número de arestas no corte
●
Eficiência: Θ(n + m), pois tem que percorrer todos os
vértices e, para cada vértice, todas as arestas
incidentes a ele
●
Qualidade da Solução: Esse algoritmo também é 1/2-
aproximado, sendo possível realizar uma demonstração
parecida com a que fizemos para o algoritmo de busca
local
Versão do Corte Máximo Ponderado
●
Neste problema temos custos nas arestas
– Os algoritmos anteriores continuam funcionando com as
mesmas garantias de qualidade, embora as demonstrações
tenham que ser levemente adaptadas para esse caso
– Mas a eficiência do algoritmo de busca local é pior nesse
caso
●
Isso porque, embora tenhamos garantia de que o valor
do corte melhora a cada iteração do algoritmo
●
No caso ponderado o valor do corte máximo pode ser
muito maior que n2
●
De fato dependendo dos pesos das arestas
●
Assim, o número de iterações da busca local, e por
consequência a eficiência do algoritmo também
dependerão dos pesos das arestas