- Algoritmos aproximados
- Garantia de execução em tempo polinomial
- Garantia de encontrar uma solução de alta qualidade (digamos, 95% do ótimo)
- Problema: temos que mostrar que uma solução está próxima do ótimo, mesmo sem saber qual é o valor ótimo!
- Resolver o problema da mochila por força bruta tem complexidade O(n2n), pois existem O(2n) combinações e levamos um tempo O(n) para verificar cada uma
- Quando estávamos estudando programação dinâmica, vimos um algoritmo para resolver o problema da mochila
- Essa abordagem tem complexidade O(n2logW), em que W é o tamanho da mochila
- Considere uma mochila com capacidade W=5, e a seguinte lista de itens:
item |
valor |
peso |
1 |
2 |
1 |
2 |
4 |
3 |
3 |
3 |
3 |
- Nesse caso, o algoritmo guloso seleciona os itens {1,2}, que nesse exemplo é a mesma da solução ótima
- Considere uma mochila com capacidade W=1000, e a seguinte lista de itens:
item |
valor |
peso |
1 |
2 |
1 |
2 |
1000 |
1000 |
- Nesse caso, o algoritmo guloso seleciona apenas o item {1}, que neste caso está muito distante da solução ótima!
- Uma heurística melhorada que a anterior é:
- Ordenar e reindexar os itens tal que
w1v1≥w1v1...≥wnvn
- Selecionar os itens em ordem até que algum não caiba, e paramos
- retornar o máximo entre o passo 2 ou o item de maior valor
- Teorema: o algoritmo guloso de 3 passos encontra uma solução que sempre é maior que 50% da solução ótima.
- Prova: no passo 2, suponha que o algoritmo seleciona os primeiros k itens, ordenados pela razão valor/peso.
- Seja c(S) o valor da solução do algoritmo de 3 passos
- Seja c(Sk) o valor da solução de selecionar os primeiros k itens
- Seja vk+1 o valor do item k+1
-
Como no passo 3 pegamos o máximo entre os k primeiros itens que cabem na mochile ou os itens remanescentes, temos que
c(S)≥c(Sk)(1)
c(S)≥vk+1(2)
-
Combinando (1) e (2), temos que
2c(S)≥c(Sk+1)(3)
- O item k+1 não cabe na mochila, mas vamos assumir que podemos selecionar uma fração dele (como na mochila fracionária)
- Seja c(Sk+1′) o valor dessa mochila fracionária hipotética, e S∗ o valor da solução ótima
- Na mochila fracionária preenchemos a mochila completamente e de maneira ótima, então a solução gulosa da mochila fracionária deve ser maior ou igual ao da solução ótima inteira
-
Resumindo:
2c(S)≥c(Sk+1)(3)
c(Sk+1′)≥c(S∗)(4)
-
Combinando (3) e (4), temos que
2c(S)c(S)≥c(S∗)≥2c(S∗)
o que prova o teorema
-
Objetivo: para um parametro ϵ especificado pelo usuário, queremos garantir (1−ϵ)% de aproximação
-
Limitação: o tempo de execução aumenta a medida que ϵ diminui. (estamos trocando tempo computacional por garantia de qualidade)
-
Ideia em alto nível: resolver de maneira exata um problema aproximado, mas que é mais fácil de resolver
-
Para o problema da mochila, podemos arredondar o valor dos itens para um inteiro pequeno.
-
Existe uma varição do algoritmo que executa em O(n2Vmax), em que Vmax=maxvi
- Por exemplo considere uma mochila com capacidade W=11. O valor original na tabela da esquerda pode ser aproximado pelos valores da tabela da direita
item |
valor |
peso |
1 |
134.221 |
1 |
2 |
656.342 |
2 |
3 |
1.810.013 |
5 |
4 |
22.217.800 |
6 |
5 |
28.343.199 |
7 |
item |
valor |
peso |
1 |
1 |
1 |
2 |
6 |
2 |
3 |
18 |
5 |
4 |
222 |
6 |
5 |
283 |
7 |
- Arredondar os valores, dividindo por um parâmetro θ :
vi^=⌊θvi⌋
- Em que o parâmetro m é definido em função do parâmetro de qualidade ϵ especificado pelo usuário:
θ=nϵ⋅Vmax
- Na primeira versão do algoritmo de programação dinâmica,
Qual é o valor máximo que conseguimos colocar no espaço W, considerando os primeiros n−1 itens.
- Uma maneira diferente de abordar o problema é
Qual é o espaço mínimo necessário para obter valor X com os primeiros primeiros n−1 itens
- Na primeira versão do algoritmo de programação dinâmica, temos a relação de recorrência
Vn,W={max{Vn−1,W,Vn−1,W−wn+vn}Vn−1,W se wn≤W se wn>W
- Na segunda versão, temos:
Vn,W={min{Vn−1,X,Vn−1,X−vn+wn}Vn−1,X se vn≤X se vn>X
Comparando algoritmos
- Força Bruta: O(n2n)
- Primeiro algoritmo de programação dinâmica O(nW)=O(n2logW)
- Segundo algoritmo de programação dinâmica O(nV)=O(n2logV)
- Casos especiais:
- Podemos usar o primeiro algoritmo se a capacidade da mochila é pequena e fixada
- Podemos usar o segundo algoritmo se o valor total é fixado
-
Para uma solução S, seja c(S) o valor da solução no problema original, e c′(S) o valor da solução do problema aproximado.
-
Seja S∗ a solução ótima no problema original, e S′∗ a solução ótima no problema simplificado
-
Queremos achar um limite para
c(S∗)−θc′(S′∗)
-
O valor da soluçõa ótimos é c(S∗), e nossa aproximação retorna θc′(S′∗)
- Observe que
c′(S′∗)≥c′(S∗)
- Raciocínio: S′∗ é a solução ótima para o problema reduzido, então o seu valor no problema reduzido é pelo menos o valor de qualquer solução de qualquer solução no problema reduzido, incluindo S∗
- Então
c(S∗)−θc′(S′∗)≤c(S∗)−θc′(S∗)
- Agora observe que:
c(S∗)−θc′(S∗)=i∈S∗∑vi−θi∈S∗∑⌊θvi⌋=i∈S∗∑(vi−θ⌊θvi⌋)<i∈S∗∑θ=nθ
Então c(S∗)−θc′(S∗)≤nθ
- Substituindo, temo que:
c(S∗)−θc′(S′∗)c(S∗)−nθ≤nθ≤θc′(S′∗)
- Se nθ≤ϵc(S∗), então (1−ϵ)c(S∗)≤c′(S′∗), então temos que escolher θ≤nϵc(S∗)
- Um limite inferior para c(S∗) é o item de maior valor Vmax que cabe na mochila. Então podemos escolher
θ≤nϵVmax
-
Para qualquer θ, o tempo de execução é O(nV/θ)
-
Já que θ=nϵVmax, o tempo de execução é O(n2ϵVmaxV)
-
Observe que V≤nVmax, então o tempo de execução é O(ϵn3)
-
Um esquema de aproximação completamente em tempo polinomal (FPTAS - do inglês Fully Polinomial-Time Approximation Scheme) é um esquema de aproximação em que o tempo é polinomial no tamanho da entrada e 1/ϵ
- Alguns (mas não todos) algoritmos NP-difíceis podem ser aproximados usando FPTAS
- Mesmo que P=NP, ainda assim podemos aproximar a resposta para uma precisão arbitrária em tempo polinomial
- Se você optar por uma solução aproximada, em muitos casos você existem algoritmos eficientes
- Um Ciclo Hamiltoniano em um grafo não dirigido G é um ciclo simples que visita todos os nós de G
- Dado um grafo G completo e não dirigido, o problema do caixeiro viajante (TSP, do inglês Traveling Salesperson Problem) consiste em encontra o ciclo Hamiltoniano de custo mínimo
Custo 47
- Dado um grafo G completo e não dirigido, o problema do caixeiro viajante (TSP, do inglês Traveling Salesperson Problem) consiste em encontra o ciclo Hamiltoniano de custo mínimo
Custo 39
-
Dado um grafo G completo e não dirigido, o problema do caixeiro viajante (TSP, do inglês Traveling Salesperson Problem) consiste em encontra o ciclo Hamiltoniano de custo mínimo
-
Observe que se o grafo é completo, deve existir pelo menos um ciclo Hamiltoniano
-
Esse problema é conhecido como sendo NP-Difícil
- Uma solução por força bruta consiste em testar todos os ciclos Hamiltonianos
- Quantos ciclos Hamiltonianos existem?
Resposta: (n−1)!/2
- Cosumimos O(n) para processar cada ciclo
- Tempo total: O(n!)
- O que é completamente impraticável
- Seja C(v,S) o custo mínimo de um caminho {1,2,⋯,v} que o último vértice é v, e passa por todos os vértices de G
- Seja u o penúltimo vértice desse caminho, e w(u,v) o custo da aresta (u,v). Devemos usar (u,v) se o caminho {1,2,⋯,u} é ótimo, mais o custo w(u,v), levando a seguinte equação de recorrência:
Cv,S={minu∈S∖v{C(u,S∖v)+w(u,v)}0 se wn≤W se v=s e S={s}
-
Podemos usar programação dinâmica para armazear os subconjuntos de vértices já calculadas
-
A ideia consiste em avaliar a equção de recorrência em conjuntos de tamanho crescente (1,2,⋯,n)
-
Existe O(2n) possíveis permutações de S.
-
Podemos mapear cada subconjunto em um número inteiro usando uma máscara binária. Isso leva a um custo adicional de O(n) para calcular a máscara que não contenha v.
- Em resumo, temos O(n2n) subproblemas
- Resolver um subproblema de tamanho n requer que analisemos O(n) subproblemas, com um custo adicinal de O(1) para cada
- O custo da abordagem de programação dinâmica é O(n22n)
- Ainda é exponencial, mas compare o tempo para diferente entradas:
tamanho |
força bruta |
programação dinâmica |
20 |
20!≈2.4×1018 |
220202≈4.2×108 |
30 |
30!≈2.6×1032 |
230302≈9.7×1011 |
40 |
40!≈8.2×1047 |
240402≈1.8×1015 |
- Melhorar com relação à força bruta aumenta o tamanho dos problemas que conseguimos resolver em um tempo razoável
- Provavelmente não é possível encontrar uma aproximação para o TSP com garantia ϵ e tempo polinomial
- Se relaxarmos o problema para desconsiderar os pesos, reduziriamos o problema a encontra um ciclo Hamiltoniano qualquer, que também não tem uma solução polinomial
- Uma heurística para resolver o TSP consiste em encontrar a árvore geradora mínima (TSP)
- Uma heurística para resolver o TSP consiste em encontrar a árvore geradora mínima (TSP)
- Retornar o ciclo no pecurso em ordem da árvore
- Uma heurística para resolver o TSP consiste em encontrar a árvore geradora mínima (TSP)
- Retornar o ciclo no pecurso em ordem da árvore
Ciclo Hamiltoniano a partir da MST
Solução ótima para o TSP
- Assumindo que a distância entre os nós respeita a distância euclideana, podemos encontrar um PTAS para o TSP euclideado:
- Uma aproximação cuja distância é no máximo duas vezes a do caminho ótimo pode ser encontrara em tempo polinomial usando o algoritmo de dobrar a árvore
- No máximo 1,5 vezes a do caminho ótimo pode ser encontrada utilizando o algoritmo de Christofides
- Em resumo
- Se precisa de uma solução exata, em geral podemos fazer melhor que força bruta (mas ainda em tempo não polinomial)
- Se uma aproximação é suficiente, algumas vezes podemos encontrar algoritmos eficientes com garantia de proximidade.