Você está na página 1de 35

Aula 25 – Busca Local p/ Problema Corte Máximo

25089/1001525 – Projeto e Análise de Algoritmos


2019/2 - Turma A
Prof. Dr. Murilo Naldi

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

1) Como escolher a solução inicial?


Questões Avançadas de Busca Local

1) Como escolher a solução inicial?


– Se possível, usando uma heurística construtiva,
como um algoritmo guloso
– Se não for possível, usando aleatoriedade e
repetindo este procedimento diversas vezes, para
aumentar a chance de que a solução obtida
possua alguma qualidade
Questões Avançadas de Busca Local

2) Dentre os vários vizinhos melhores que a solução


atual, qual escolher?
Questões Avançadas de Busca Local

2) Dentre os vários vizinhos melhores que a solução


atual, qual escolher?
– Aleatoriamente, para aumentar diversidade
– Primeiro encontrado, buscando aumentar
eficiência
– Maior melhoria, buscando aumentar qualidade

Destacar que não há garantia de que essas
escolhas reflitam os resultados esperados

Testes empíricos são essenciais quando
lidamos com busca local
Questões Avançadas de Busca Local

3) Como definir vizinhanças?


Questões Avançadas de Busca Local

3) Como definir vizinhanças?


– Vizinhanças muito pequenas permitem buscas mais
rápidas, mas podem parar em ótimos locais muito
ruins
– Vizinhanças muito grandes evitam ótimos locais
piores, mas podem ser lentas de buscar
– Em geral, procurar um meio termo

Algumas técnicas usam vizinhanças de tamanhos
variados, migrando de uma para outra em
momentos específicos
– Quando uma menor e mais rápida não
encontra mais avanço, por exemplo
Questões Avançadas de Busca Local

4) Busca local sempre termina?


Questões Avançadas de Busca Local

4) Busca local sempre termina?


– Em geral sim, pois a solução ótima tem valor
finito e a busca está sempre melhorando

Exceção é se as melhorias forem cada vez
menores
Questões Avançadas de Busca Local

5) Busca local é rápida?


Questões Avançadas de Busca Local

5) Busca local é rápida?


– Pior caso em geral é exponencial, mas costuma
ser rápida na prática, especialmente se partir de
soluções iniciais razoáveis
Questões Avançadas de Busca Local

6) Busca local gera soluções com garantia de


qualidade?
Questões Avançadas de Busca Local

6) Busca local gera soluções com garantia de


qualidade?
– Em geral não, mas são muito boas em melhorar
outras soluções
O problema do Corte Máximo


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

Você também pode gostar