Sei sulla pagina 1di 24

FUNDAÇÃO EDSON QUEIROZ

UNIVERSIDADE DE FORTALEZA
CENTRO DE CIÊNCIAS TECNOLÓGICAS
TÓPICOS ESPECIAIS DE OTIMIZAÇÃO
NOTAS DE AULA

Uma Introdução a Complexidade de Algoritmos

Plácido Rogério Pinheiro

2001

Pesquisa Operacional / Uma Introdução a Complexidade 1


Introdução:

O presente trabalho é uma coletânea de textos, construída através de dissertações, livros


e manuais de softwares. Dentre estes podemos destacar a dissertação do Prof. Geraldo Valdisio
Rodrigues Viana do Departamento de Computação da Univ. Federal do Ceará intitulada “Meta-
Heurísticas para Solução de Problemas de Otimização Combinatória”. Outros textos
consultados foram os livros “Discrete Optimization Algoritms with Pascal Programs” de
Maciej M. Syslo et alli e Operations Research, Applications and Algorithms de Wayne L.
Winston. O apoio computacional, foi obtido através do software LINGO, da LINDO
SYSTEMS INC.

Pesquisa Operacional / Uma Introdução a Complexidade 2


1. Conceitos Básicos

1.1 Partição de um Conjunto

Seja A um conjunto não vazio. Chama-se partição de A, ao conjunto P com as seguintes propriedades.

i) todos elementos de P são subconjuntos de A não vazios;


ii) os elementos de P são disjuntos e
iii) a união dos elementos de P é igual ao conjunto A.
Exemplo 1.1
A = { 2, 3, 5, 7, 11, 13, 17, 19 }
P = { { 2, 3, 5 } , { 7, 11 } , { 13, 17, 19 } } Onde:
• Número de Elementos de A: |A|=8
• Número de Elementos de P: |P|=3
• Número de subconjuntos não vazios de A: | P(A) | = 2 | A | − 1 = 255
• P1 = { 2, 3, 5 }; P2 = { 7, 11 } ; P3 = { 13, 17, 19 }
• P1 I P2 = P1 I P3 = P2 I P3 = φ
• P1 U P2 U P3 = A

1.2 Notação “O”

Essa notação é usada para expressar a complexidade de tempo de execução de um algoritmo, em função
de um valor “n” que correspondente ao tamanho da entrada do problema. Assim, O( f(n) ) indica que o tempo
necessário para obter um resultado do algoritmo é proporcional a f(n).

Essa medida tem por objetivo avaliar a eficiência do algoritmo em termos de sua complexidade,
normalmente considerada no pior caso. O valor de f(n) não tem uma relação exata com o tempo e sim com
sua ordem de grandeza, o que serve de parâmetro de comparação entre diferentes algoritmos; por exemplo,
para valores de “n” suficientemente grandes as funções f1 (n) = n2 , f2 (n) = 2.n2 + 3 e f3 (n) = 3.n2 , têm a
mesma ordem de grandeza, a qual é proporcional a n2 , ou seja, O(n2). Observe na Tabela 2.1 que a medida
que “n” cresce as ordens de grandeza ( potências de 10 ) de f1 , f2 e f3 tornam-se iguais.

Pesquisa Operacional / Uma Introdução a Complexidade 3


N f1 (n) = n2 f2 (n) = 2.n2 + 3 f3 (n) = 3.n2
5 25 53 75
10 100 203 300
5003 ≈ 0.50x104
4
50 2500 = 0.25x10 7500 = 0.75x104
1000 0.10x107 0.20x107 0.30x107
50000 0.25x10 10 0.50x1010 0.75x1010
Tabela 2.1 - Função de Complexidade O (n2 )

Por definição, se existir uma função g(n) tal que f(n) ≤ c.g(n) , para uma constante c > 0, diremos que
O( f(n) ) = O( g(n) ).

Normalmente a função “g” representa uma família de funções conhecidas como: O(n), O(n2 ), O(n3 ),
O(2n), O(n!), O(log2 n), O(n.log2 n), etc. A notação O(1) é usada para indicar uma complexidade constante,
ou seja, independente de “n”; no entanto, isso é bastante incomum.

No exemplo anterior observa-se que: n2 ≤ 3n2 e 2n2 + 3 ≤ 3n2 ; logo, c=3 e a função g(n) = n2 .
Cuidados devem ser tomados para valores de “c” elevados, pois, é óbvio que f1 = (50!).n e f2 = 3n não tem
realmente a mesma ordem de grandeza; casos como estes devem ter tratamento especial. A Tabela 2.2
permite fazer uma comparação entre funções comumente usadas na medição da complexidade de um
algoritmo para alguns valores de “n”.

Para uma melhor visualização, os valores indicados representam o tempo médio esperado de execução,
expressos em segundos quando não indicado. Foi considerado o tempo de 1 µs para cada ciclo.

Pesquisa Operacional / Uma Introdução a Complexidade 4


Complexida n=5 n=10 n=50 n=100 N=1000 n=10000
de
O ( log 2 n ) 0.000002 0.000003 0.0000056 0.0000066 0.0000099 0.000013
3 3
O (n) 0.000005 0.000010 0.000050 0.000100 0.001000 0.010000
O ( n.log2n ) 0.000011 0.000033 0.000283 0.000684 0.009966 0.132877
2
O(n ) 0.000025 0.000100 0.002500 0.010000 1s 1min 40s
3
O(n ) 0.000125 0.001000 0.125000 1s 16min 40s 11dias
14h
O ( n5 ) 0.003125 0.100000 5min 13s 2h 47min 32 anos ∞
O ( 2n ) 0.000032 0.001024 35 anos 4x1016 ∞ ∞
anos
O ( 3n ) 0.000243 0.059049 2x10 10 ∞ ∞ ∞
anos
Tabela 2.2 - Funções de Complexidade mais Comuns

De acordo com análise feita na Tabela 2.2 concluímos que para valores de “n” não superiores a 1000 a
complexidade cúbica O(n3 ) seria a máxima admitida. Para grandes conjuntos de dados ( n ≥ 10000 ) o ideal
seria a complexidade não superior a O(n2 ). Em geral, O(nm) para m > 3, ou complexidade exponencia l, são
indesejáveis.

Posteriormente, no item 2.7, veremos que os problemas são classificados em função da complexidade
de seus algoritmos. No item 2.5 daremos uma idéia, através de alguns exemplos, como se obtém esta função
de complexidade.

Um outro fator a ser considerado é que, em função da ordem de complexidade, um aumento da


velocidade do computador pode ser irrelevante em relação ao tempo de execução do algoritmo.

Era de se esperar que, se um computador resolve um problema de tamanho “n” num determinado
tempo, um outro, de velocidade 100 vezes maior, deveria resolver neste mesmo tempo um problema similar
de tamanho “100.n”.

Entretanto, conforme podemos observar na Tabela 2.3, isto não ocorre. Veja que para complexidade
O(n3), um aumento de 1000 vezes na velocidade, corresponde a um aumento de 10 vezes no tamanho; ou,
para o mesmo caso, se a complexidade fosse O(10n ) o aumento no tamanho seria de apenas 3 unidades (valor
constante).

Pesquisa Operacional / Uma Introdução a Complexidade 5


Ordem Tamanho no Computador Computador
de Computador 100 vezes mais 1000 vezes
Complexidad Atual rápido mais rápido
e
O (n) N1 100.N1 1000.N 1
2
O(n ) N2 10.N2 31,62.N 2
3
O(n ) N3 4,64.N3 10.N 3
5
O(n ) N4 2,51.N4 3,98.N 4
n
O(2 ) N5 N5 + 6,64 N 5 + 9,97
n
O(3 ) N6 N6 + 4,19 N 6 + 6,29
O ( 10n ) N7 N7 + 2 N7 + 3
Tabela 2.3 - Efeito da Velocidade do Computador x Tamanho do Problema num dado tempo 2

1.3 Tempo Computacional

O tempo de execução de cada operação aritmética depende da forma de cálculo e da velocidade do


processador. Para as funções, além destes fatores, deve ser consideradas ainda sua forma de implementação e
a linguagem de programação utilizada.

Por isso, temos variação na medição deste tempo para diferentes compiladores e ambientes
computacionais, mas invariavelmente, as operações de soma ( + ) e subtração ( − ) tem tempo quase igual e
bem menor que a multiplicação ( * ) e divisão ( / ). Entre as funções, geralmente a raiz quadrada ( sqrt ) é a
mais rápida, enquanto que as funções: logaritmo ( log ), seno ( sin ), cosseno ( cos ), exponencial ( exp ) e
arcotangente ( arctg ) são intermediárias quando comparadas com a potenciação com expoente não inteiro (
xy , y∈ℜ ) e a função tangente ( tg ) que se apresentam como as menos rápidas.

Para avaliação destas medidas utilizamos o Algoritmo 2.1, onde clock() é uma função que fornece o
tempo atual em segundos e o símbolo Θ substitui um dos operadores ( +, −, * , / , ^ ) na expressão S = X Θ Y
para dois valores arbitrários de X e Y. Quando S = f (X) , f representa uma das funções citadas
anteriormente.

2
Tabela semelhante à contida na referência [GAR79] p.8
Pesquisa Operacional / Uma Introdução a Complexidade 6
{Início – A2.1}
ler (X,Y)
T1 = clock()
{ Computa tempo de: “loop”, “+” e “=” }
enquanto (I ≤ 1000000) faça
I = I +1
S=I
fim_enquanto
T2 = clock()
TLOOP = T2 − T1
I=0
{ Computa tempo da operação Θ (ou f ) }
enquanto (I ≤ 1000000) faça
I = I +1
S=XΘY { ou S = f (X) }
fim_enquanto
T1 = clock()
T = T1 − T2 − TLOOP
imprimir (T)
{Fim - A2.1}
Algoritmo 2.1 - Avalia Tempo Computacional de uma Operação ou Função

Obtivemos os resultados apresentados na Tabela 2.4 codificando o algoritmo na linguagem Fortran,


utilizando o Microsoft Fortran Optmizing Compiler Version 5.0 [MIC89] num microcomputador AT486- DX
com co-processador aritmético e 8 MB de RAM 3 .

Os valores representados indicam o tempo médio em µs ( 10−6 s ), e a coluna “Unidade” mostra a


relação entre a medição do tempo do operador ou função com a operação básica de adição.

Vale lembrar que a composição destes tempos depende da máquina utilizada e em geral estes valores
encontram-se em manuais específicos for necidos pelos fabricantes.

3
RAM (Random Access Memory) significa Memória de Acesso Randômico ou Memória Principal
Pesquisa Operacional / Uma Introdução a Complexidade 7
Operação / Tempo Médio Unidade
Função ( em µs ) (Tempo
Relativo)
+ 0.5 1
− 0.5 1
* 2.8 6
/ 3.0 6
sqrt 7.2 14
log 14.4 29
sin 15.9 32
cos 15.9 32
arctg 16.2 32
exp 20.3 40
^ 34.52 69
tg 34.84 70
Tabela 2.4 - Tempo Computacional para Operações e Funções

Com estes resultados, é esperado que se um determinado programa que só realiza operações de adição (
+ ) necessita de 1 segundo para sua execução, seria necessário em torno de 69 segundos quando esta
operação fosse trocada pela potenciação ( ^ ).

Sem perda de generalidade, poderíamos computar as operações e funções num dado algoritmo
indistintamente, apesar dos tempos de processamento serem diferentes. Isso é válido porque levamos em
consideração apenas a ordem de grandeza deste tempo em função da complexidade do algoritmo. Por
exemplo, se t1 , t2 e t3 são respectivamente os tempos computacionais para cálculo das funções logaritmo (
log(x) ) e raiz quadrada ( sqrt(x) ) e da operação de multiplicação (*) temos que t 1 ≈ 2 t2 ≈ 5 t3 .

Ou seja, a grosso modo poderíamos substituir o cálculo de log(x) pelo cálculo de sqrt(x) duas vezes ou
pela computação da operação “*” cinco vezes, isso sem alterar o tempo de execução do processo; de forma
que, se f 1 , f2 e f3 são seus respectivos algoritmos teríamos, O( f 1 ) = O( 2.f 2 ) = O( 5.f 3 ) , ou O( f1 ) = O( f 2
) = O( f 3 ), pois conforme citado anteriormente, O( f ) = O( c.f ), sendo “c” uma constante positiva.

Poder-se-ia também esperar que a expressão:

Pesquisa Operacional / Uma Introdução a Complexidade 8


z= sin ( x ) * ( x ^ y ) / log( x + y )

seria executada nessa máquina num tempo aproximado de 78.3 µs, conforme mostra a ordem de execução
das operações indicadas na Tabela 2.5 (foi considerado desprezível o tempo de execução do comando de
atribuição).

Passo Operador Operação Realizada Resultado Tempo (µs)


1 ^ x^y r1 34.5
2 + x+y r2 0.5
3 Sin sen(x) r3 15.9
4 Log log(r2) r4 14.4
5 * r3 * r1 r5 2.8
6 / r5 / r4 r6 3.0
7 Sqrt sqrt(r6) r7 7.2
8 = z = r7 z 0.0
TOTAL ⇒ 78.3
Tabela 2.5- Cálculo do Tempo Computacional na Avaliação de uma Expressão

Pesquisa Operacional / Uma Introdução a Complexidade 9


1.4 Classes de Problemas

1.4.1 Considerações Gerais

Antes de definirmos classes de problemas iremos relembrar que de acordo com os resultados
apresentados na Tabela 2.2, algoritmos de tempo polinomial são preferíveis aos algoritmos de tempo
exponencial. Complexidade de O( nm ), para m > 3, ou O ( xn ), para x > 1 são indesejáveis e os problemas
correspondentes são denominados de intratáveis. Mesmo nas complexidades de O ( c.n2 ), para grandes
valores de c ( c > 106 ), também são consideradas assim.

Existem problemas dificílimos, no sentido de que nenhum algoritmo pode resolvê-los; estes são
denominados indecidíveis, não-computáveis ou fortemente intratáveis.

De uma maneira geral um problema é considerado tratável quando existe um algoritmo de


complexidade polinomial que o resolva, e seria intratável quando todos algoritmos conhecidos para resolvê-
lo possuem complexidade exponencial, ou não polinomial. Uma regra para escolher um algoritmo eficiente é
que a função f(n) que estima seu tempo de execução não ultrapasse os limites desejados.

Por exemplo, sendo “n” o tamanho da entrada do problema, f (n) > 1010 já é motivo de preocupação,
pois máquinas convencionais com unidade de tempo para instruções e operações da ordem de 10− 6 segundos,
requereriam um tempo de execução em torno de 3 horas. Se f (n) > 1011 (10 vezes) este tempo já superaria
um dia e se fosse da ordem de 1014 ultrapassaria 3 (três) anos.

1.4.2 Algoritmos Determinísticos e Não-Determinísticos

Chamam-se determinísticos aqueles algoritmos que para uma dada entrada do problema apresentam
apenas uma solução. Caso sejam implementadas operações cujos resultados permitem um número finito de
soluções, então os algoritmos seriam chamados de não-determinísticos.

Existe um modelo abstrato para representação de algoritmos desta natureza, chamado de Máquina de
Turing ( Alan Mathison Turing, 1936 ) cujo detalhamento pode ser encontrado em [CAM94] p. 59-61. São
definidas primitivas que levam ao sucesso (sim) ou fracasso (não) na sinalização do término de um algoritmo
quando aplicados a uma instância genérica do problema, de forma que, se houver uma seqüência de
operações que conduza ao término com sucesso esta será verificada no menor número de passos.

Um algoritmo não-determinístico tem complexidade O ( f(n) ), para instâncias de tamanho “n” para
término com sucesso e O ( 1 ), ou constante, com término com fracasso.

Pesquisa Operacional / Uma Introdução a Complexidade 10


A chamada MTND ( Máquina de Turing Não-Determinística ) é uma máquina conceitual que
implementa algoritmos deste tipo que podem ser executados de forma determinística, onde diversas
instâncias escolhidas poderiam ser executadas “simultaneamente”, uma em cada MTD ( Máquina de Turing
Determinística ). Neste caso para término com sucesso seria considerado o resultado da primeira MTD que
encerrasse assim, provocando uma interrupção nas demais. Para detectar um término com fracasso seria
necessário que todas cópias da MTD tivessem esse resultado e que cada vez que ele fosse obtido haveria
interrupção apenas daquele processo.

1.4.3 Classes P e NP

Esta classificação, fundamentada na teoria desenvolvida por Stephen Cook [COO71], pode ser feita
através de algumas conotações.

Em termo da função de complexidade, podemos dizer que problemas com complexidade de tempo
polinomial constituem a classe P, enquanto que aqueles com tempo exponencial pertencem à classe NP.

Outra conotação desta classificação seria que problemas de decisão que admitem algoritmos
determinísticos polinomiais formam a classe P, enquanto que algoritmos não-determinísticos polinomiais
formam a classe NP.

Conjectura-se que P ≠ NP, pois diversos pesquisadores até hoje não conseguiram elaborar algoritmos
polinomiais eficientes para um grande número de problemas (veja a relação de alguns deles no item 2.7.5),
de forma que na Figura 2.23, o conjunto ( NP − P ) seria não vazio. Porém, se alguém conseguir mostrar um
algoritmo polinomial para resolver pelo menos um daqueles problemas, então P = NP, pois todos os outros
problemas poderiam ser transformados ( reduzidos ) àquele. Outra dificuldade para provar que um problema
de decisão π ∉ P, é necessário mostrar uma prova concreta que todo algoritmo possível para resolver π não é
polinomial.

Observe que P ⊆ NP, pois além das considerações feitas no item 2.7.1, tem-se que um algoritmo
determinístico é um caso particular de algoritmo não-determinístico, sendo P, portanto, uma subclasse de
NP.

Por fim indicamos que a classe NP compreende àqueles problemas de decisão π para os quais existe um
algoritmo não-determinístico para justificar a resposta “sim”, que será reconhecida por um algoritmo
polinomial; observando que uma justificativa para a resposta “não” geralmente é exaustiva.

Pesquisa Operacional / Uma Introdução a Complexidade 11


1.4.4 Classe NP-Completo e NP-Árduo

Quando existe uma transformação em tempo polinomial de um problema de decisão π 1 para outro π 2 (
escreve-se: π 1 ∝ π 2 ), mostra-se [GAR79] que se π 2 ∈ P ⇒ π 1 ∈ P, ou de forma equivalente, se π 1 ∉ P ⇒
π 2 ∉ P. Podemos então dizer que π 1 é um caso particular de π 2 ,ou seja, π 2 é pelo menos tão difícil quanto π 1 .
Observe que esta relação é transitiva, ou seja, se π 1 ∝ π 2 e π 2 ∝ π 3 então π 1 ∝ π 3 .

Um problema de decisão π é chamado de NP-Árduo ou NP-Hard se π 0 ∝ π para todo π 0 ∈ NP, logo


um problema NP-Árduo é pelo menos tão difícil quanto qualquer problema em NP.

A denominação de problemas de decisão como NP-Completo deve-se a Stephen Cook [COO83] que
estabeleceu que o problema SAT (satisfiabilidade), referido no exemplo 2.14, é o mais difícil da classe NP e
todos os outros problemas em NP podem ser reduzidos polinomialmente a ele. Portanto, a classe NP-
Completo contém os problemas de maior dificuldade entre todos em NP.

A Figura 2.23 mostra uma estrutura de problemas NP numa visão simplificada dos problemas de
decisão; os problemas NP-Árduos estão fora desta classificação.

Figura 2.23 - Estrutura de problemas de decisão NP

Uma técnica de prova para problemas NP-Completos consiste em utilizar a chamada redução mestre:
SAT ∝ π, sendo a redução feita em tempo polinomial. Neste caso, o problema de decisão π é pelo menos tão
difícil quanto SAT, logo π também é NP-Completo. Em geral, usando a propriedade transitiva, se várias
reduções da forma: SAT ∝ π 1 ∝ π 2 ∝ . . . ∝ π m podem ser feitas em tempo polinomial, então π i , ∀ i=1,...,m,
é um problema da classe N P-Completo.

Se n-SAT é uma classificação do problema SAT, onde cada cláusula tem exatamente “n” literais é fácil
verificar que 2-SAT pertence a classe P e para n≥3, n-SAT é NP. Veja o exemplo:

Pesquisa Operacional / Uma Introdução a Complexidade 12


Exemplo 2.16 Provar que: SAT ∝ 3–SAT

Passo-1: Substituir cada cláusula da forma: ( para 4 ≤ k ≤ n )


( g1 ∨ g2 ∨ . . . ∨ gk ) por: ( g1 ∨ g2 ∨ h ) ∧ ( g3 ∨ . . . ∨ gk ∨ ~h ),
onde h é um novo literal e (~h) = não-h (negação de h).
Repetir este passo sucessivamente até que todas cláusulas possuam não mais que 3 literais cada uma.
Passo-2: Substituir as cláusulas com 2 literais:
( g1 ∨ g2 ) por: ( g1 ∨ g2 ∨ h ) ∧ ( ~h∨ ~h ∨ ~h ).
Passo-3: Substituir as cláusulas com 1 literal:
( g1 ) por: ( g1 ∨ h ∨ h ) ∧ ( ~h ∨ ~h ∨ ~h ).

Essas substituições podem ser feitas em tempo polinomial, de forma que qualquer expressão n-SAT
pode ser transformada numa expressão 3-SAT.

Um problema de otimização é N P-Árduo, pois sendo composto de vários problemas de decisão seria
pelo menos tão difícil quanto estes, logo, não poderia ser NP-Completo. Assim, se π 0 for um problema de

decisão (PD) associado a um problema de otimização (PO) π, temos:

π0 ∝ π ( PO = PD1 + PD2 + . . . + PDm )

Portanto, se π 0 fosse de ordem O ( f(n) ), π seria de ordem O ( m.f(n) ), logo π só poderia ser resolvido
em tempo polinomial se π 0 também o fosse, donde se conclui que π 0 é NP-Completo e π é NP-Árduo.

Em resumo, se NPA = NP-Árduo e NPC = NP-Completo, então NPA ≥ NPC ≥ NP, onde o sinal “≥ ”
significa “de dificuldade não menor”. Concluímos também que os problemas da classe NPC são os mais
difíceis em NP, para estes não são conhecidos, ou não existem, algoritmos determinísticos, de complexidade
polinomial, para resolvê-los.

1.4.5 Problema s NP-Completos

Garey & Johnson, [GAR79] p. 190-288, apresentam uma extensa lista de problemas de decisão NP-
Completo, pertencentes às áreas de Otimização Combinatória, Teoria dos Números, Construção de
Compiladores, Planejamento de Tarefas, Teoria dos Grafos, Projeto de Redes de Computadores,
Programação Matemática, Conjuntos e Partições, Lógica, Jogos etc. Aqui selecionamos alguns deles:

Pesquisa Operacional / Uma Introdução a Complexidade 13


i) Cobertura de Vértices ( Vertex Cover )

Entrada : Grafo G = ( V, E ) e inteiro positivo k ≤ | V |


Questão : ∃ cobertura em G de tamanho ≥ k ?
Redução:3-SAT [KAR72]

ii) Número Cromático ( Chromatic Number )

Entrada : Grafo G = ( V, E ) e inteiro positivo k ≤ | V |


Questão : G é k-colorável ?
Redução:3-SAT [KAR72]

iii) Clique ( Clique )

Entrada : Grafo G = ( V, E ) e inteiro positivo k ≤ | V |


Questão : ∃ clique em G de tamanho ≥ k ?
Redução:Cobertura de Vértices [KAR72]

iv) Conjunto Independente de Vértices ( Independent Set )

Entrada : Grafo G = ( V, E ) e inteiro positivo k ≤ | V |


Questão : ∃ conjunto independente de vértices de tamanho ≥ k ?
Redução:Cobertura de Vértices [KAR72]

v) Subgrafo Bipartido ( Bipartite Subgraph )

Entrada : Grafo G = ( V, E ) e inteiro positivo k ≤ | E |


Questão : ∃ E′ ⊆ E , com | E′ | ≥ k tal que G′ = (V, E′ ) é bipartido ?
Redução:Máximo 2-SAT [GAR76]
vi) Subgrafo Planar ( Planar Subgraph )

Entrada : Grafo G = ( V, E ) e inteiro positivo k ≤ | E |


Questão : ∃ E′ ⊆ E , com | E′ | ≥ k tal que G′ = (V, E′ ) é planar ?
Redução:Ciclo Hamiltoniano [LIU78]

Pesquisa Operacional / Uma Introdução a Complexidade 14


vii) Circuito Hamiltoniano ( Hamiltonian Circuit )

Entrada : Grafo direcionado G = ( V, E ).


Questão : G contém um Circuito Hamiltoniano ?
Redução:Cobertura de Vértices [KAR72]

viii) Caminho Hamiltoniano ( Hamiltonian Path )

Entrada : Grafo G = ( V, E ).
Questão : G contém um Caminho Hamiltoniano ?
Redução:Cobertura de Vértices [KAR72]

ix) Isomorfismo de Subgrafos ( Subgraph Isomorphism )

Entrada : Grafos G = ( V1 , E1 ) e H = ( V2 , E2 ).
Questão : G contém um subgrafo isomorfo à H ?
Um subgrafo G′ = ( V, E ) de G, V ⊆ V1 e E ⊆ E1 , é isomorfo a um grafo H, se | V | =
| V2 |, | E | = | E2 | e ∃ f : V2 → V {u, v} ∈ E2 ⇔ { f (u) , f (v) } ∈ E.
Redução:Clique [COO71]

x) Caixeiro Viajante ( Traveling Salesman )

Entrada : Conjunto C com “m” cidades; distância d ( ci , cj ) ∈ Z+ para cada par de cidade ci , cj
∈ C; e um inteiro positivo B.
Questão : ∃ uma permutação < ck(1) , ck(2) , ... , ck(m) > tal que:
 m−1 
∑ d ( ck ( i ) , c k ( i+1) ) + d ( ck ( m) , ck (1) ) ≤ B ? ?
 i=1 
Redução:Circuito Hamiltoniano [KAR72]

xi) Carteiro Chinês ( Chinese Postman )

Entrada : Grafo misto G = (V, A, E), onde A é o conjunto de arestas direcionadas e E o conjunto
de arestas não-direcionadas de G; tamanho L(e) de cada aresta e ∈ (A ∪ E); e um inteiro positivo B.
Questão : ∃ um ciclo em G que inclui cada aresta (direcionada ou não) pelo menos uma vez com
tamanho total ≤ B ?
Redução:3-SAT [PAP76]

Pesquisa Operacional / Uma Introdução a Complexidade 15


xii) Partição ( Partition )

Entrada : Conjunto finito A e um tamanho s(a) ∈ Z+ para cada a ∈ A.


Questão : ∃ um subconjunto A′⊆ A, tal que: ∑ a ∈A'
s( a ) = ∑a∈A− A' s( a ) ?
Redução:3DM (“Matching ” em 3-D) [KAR72]

xiii) Soma dos Elementos de um Subconjunto ( Subset Sum )

Entrada : Conjunto finito A; um tamanho s(a) ∈ Z+ para cada a ∈ A e um inteiro positivo B.


Questão : ∃ um subconjunto A′⊆ A, tal que ∑ a ∈A '
s( a ) = B ?

Redução:Partição [KAR72]

xiv) Produto dos Elementos de um Subconjunto ( Subset Product )

Entrada : Conjunto finito A; um tamanho s(a) ∈ Z+ para cada a ∈ A e um inteiro positivo B.


Questão : ∃ um subconjunto A′⊆ A, tal que ∏ s( a ) = B ?
a ∈A'

Redução:X3C ( Cobertura Exata para conjuntos de cardinalidade 3)


[YAO78]

xv) Empacotamento ( Bin Packing )

Entrada : Conjunto finito U de itens; um tamanho s(u) ∈ Z+ para cada u ∈ U e os inteiros


positivos B, capacidade da caixa (bin), e k.
Questão : ∃ uma partição de U (ver definição no item 2.1), tal que a soma de todos itens de cada
partição Ui é ≤ k ?
Redução:Partição [KAR72]

xvi) Escalonamento de Tarefas ( Multiprocessor Scheduling )

Entrada : Conjunto finito T de tarefas; um número m ∈ Z+ de processadores, tamanho L(u) ∈ Z+


para cada u ∈ T e um tempo limite D ∈ Z+.
Questão : ∃ σ: T → Z0 + tal que ∀ u ≥ 0, σ(t) ≤ u ≤ σ(t) + L(t), o número de tarefas t ∈ T é
menor ou igual a “m” e σ(t) + L(t) ≤ D ?
Redução:Partição [KAR72]

Pesquisa Operacional / Uma Introdução a Complexidade 16


xvii) Programação Inteira ( Integer Programming )

Entrada : Conjunto finito X de pares ( x , b), onde x é uma m-tupla de inteiros e “b” um inteiro;
uma m-tupla c de inteiros e um inteiro B.
Questão : ∃ uma m-tupla y de inteiros tal que x.y ≤ b para todo ( x , b) ∈ X e tal que c.y ≥ B.
Obs.: u.v é o produto escalar do vetor u = ( u1 , u2, ... , um ) pelo vetor v = ( v1, v2 , ... , vm ), ou seja, u.v =
u1 .v1 + u2 .v2 + ... + um .vm.
Redução:3-SAT [KAR72]

xviii) Programação Quadrática ( Quadratic Programming )

Entrada : Conjunto finito X de pares ( x , b), onde x é uma m-tupla de reais e “b” um real; duas
m-tuplas c e d de reais e um real B.
Questão : ∃ uma m-tupla y de reais tal que x.y ≤ b para todo ( x , b) ∈ X e tal que

m
( ci . y i + d i . yi ) ≥ B , onde ci , d i , yi são os i- ésimos componentes de c, d e y, respectivamente.
2
i =1

Redução:Partição [SHA74]

xix) Problema da Mochila ( Knapsack Problem )

Entrada : Conjunto finito U de itens; um tamanho s(u) ∈ Z+ para cada u ∈ U e um valor v(u) ∈
Z+ e os inteiros positivos B e K
Questão : ∃ U′⊆ U tal que ∑ u∈U '
s( u) ≤ B e ∑ u∈U '
v (u) ≥ K ?

Redução:Partição [KAR72]
xx) Números Compostos ( Composite Numbers )

Entrada : Inteiro positivo N.


Questão : ∃ inteiros positivos, m e n, tais que N = m.n ?

Pesquisa Operacional / Uma Introdução a Complexidade 17


1.4.6 Complexidade Computacional do Método Simplex

Introdução

Durante vários anos, o método simplex pareceu bastante eficiente do ponto de vista
computacional. Entretanto várias questões fo ram abordadas tais como:

O Método Simplex tem complexidade polinomial?

Em termos mais amplos podemos abordar as seguintes questões:

♦Como podemos comparar dois diferentes algoritmos para o mesmo problema?


• Qualidade da Solução
• Eficiência Computaciona l
Uma medida muitas vezes usada para dimensionar a eficiência computacional é o
tempo de execução do computador(cpu time). Porém o “cpu time” depende do tipo de
computador, linguagem de programação, habilidade do programador, etc.

Princípio da Invariância
O princípio da invariância diz que duas diferentes implementações do mesmo
algoritmo não diferirão em eficiência computacional por mais que uma constante
mult i plicativa.

Sejam duas implementações computacionais do mesmo algoritmo, que podem


diferir na languagem de programação e/ou máquina usada. Então tome t1(n) e
t2(n) segundos para o instante de tamanho n, logo existe uma constante c > 0 e
um inteiro N tal que t1(n) ≤ ct2(n) para todo n ≥ N

Um caminho apropriado para medir a eficiência computacional é contar o número d e


operações elementares que são requeridas pelo algoritmo, i.e., adições, subtrações,
m u l t i p licações, divisões, comparações, etc.
Especificamente, nos calculamos o pior- caso “worst- case” do número de

Pesquisa Operacional / Uma Introdução a Complexidade 18


o p e ra ções elementares, que pode ser bastante diferente de um caso típico encontrado
em aplica ções.
Do ponto de vista “macro”, contaríamos o número de iterações que o algoritmo tem
que executar como uma t(n) função de tamanho n do problema se o esforço de
co mputacional por iteração é estável, por exemplo, limit ada por alguma função de n.
Dizemos que um algoritmo toma um tempo de ordem t(n), onde t é uma dada funç ã o ,
se existem um c > 0 e uma implementação do algoritmo capaz de resolver qualquer
instância do problema de tamanho n em um tempo limitado por ct(n).

Isto é denotado por O(t(n)) e é chamado o tempo de complexidade do algoritmo

Definição: Sejam f:Á → Å + e g:Á → Å + duas funções, a notação f∈O(g), que se lê: “f é

da ordem de g”, significa que existe uma constante k > 0 e n0 ∈ Á, tal que f(n) ≤ k.g(n) para
todo n > n0 .
Propriedade: Se f:Á → Å + e g :Á → Å + são duas funções tais que f(n) ≤ g(n), então

O(f(n))⊂ O(g(n)) para todo n ∈ Á.


Em resumo, tem-s e :
O(1) ⊂ O(logn) ⊂ O(n) ) ⊂ O(nlogn) ) ⊂ O ( n2 ) ) ⊂ O ( kn ) ) ⊂ O ( n ! )

Algoritmo de Tempo Polinomial


Um algoritmo para o qual o tempo (equivalentemente, o número de operações) é
O(p(n)), onde p(n) é uma função polinomial e n é o “tamanho” do problema é
chamado algoritmo de tempo polinomial.

Algoritmo de Tempo Exponencial


Um algoritmo para o qual o tempo é O(exp(n)), onde exp(n) é uma função
exponencial e n é o tamanho do problema.

Pesquisa Operacional / Uma Introdução a Complexidade 19


O algoritmo simplex possui complexidade exponencial
Considere o problema de Klee-Minty(1972):
n
max Z = ∑10 n- j x j
j=1

i −1
s.a ( 2∑10 i− j x j ) + x i ≤ 100 i −1 (i = 1, 2,..., n )
j=1

xj ≥ 0 (j=1,2,...,n)

Para n = 2 tem- se
máx Z = 10x1 + x2
s.a x1 ≤ 1
2 0 x1 + x2 ≤ 100
x1 ≥ 0, x2 ≥ 0

Graficamente:

P (0, 100)⇒ z = 100 (sol. ótima)


(0,100) P (0, 0) ⇒ z = 0
P (1, 0) ⇒ z = 10
P (1, 80) ⇒ z = 90
(1,80)

(0,0)
(1,0) (5,0)

Pesquisa Operacional / Uma Introdução a Complexidade 20


Apresentaremos a seguir todas as soluções básicas viáveis para este PPL

Fazendo z’ = -z
Mín z’ = -10x1 – x2
s.a x1 + x3 =1
20x1 + x2 + x4 = 100
x1, x2 ≥ 0

Base X1 X2 X3 X4 B
X3 1 0 1 0 1
X4 20 1 0 1 100
- Z’ -10 -1 0 0 0

VB à X3 = 1; X4 = 100; VNB à X1 = X2 = 0; X1 entra e X3 sai

Base X1 X2 X3 X4 B
X1 1 0 1 0 1
X4 0 1 -20 1 80
- Z’ 0 -1 10 0 10

VB à X1 = 1; X4 = 80; VNB à X2 = X3 = 0; X2 entra e X4 sai

Base X1 X2 X3 X4 B
X1 1 0 1 0 1
X2 0 1 -20 1 80
- Z’ 0 0 -10 1 90

VB à X1 = 1; X2 = 80; VNB à X4 = X3 = 0; X3 entra e X1 sai

Base X1 X2 X3 X4 B
X3 1 0 1 0 1
X2 20 1 0 1 100
- Z’ 10 0 0 1 100

VB à X3 = 1; X2 = 100; VNB à X1 = X4 = 0
Pesquisa Operacional / Uma Introdução a Complexidade 21
Para n = 3 tem-se
Máx Z = 100x1 + 1 0 x2 + x 3
s.a x1 ≤ 1
2 0 x1 + x2 ≤ 100
2 0 0 x1 + 20x2 + x3 ≤ 10000
xi ≥ 0, i = 1,2,3
Quando o simplex é usado pa ra resolver este PPL, toda solução básica viável deve
ser examinada antes da solução ótima ser descoberta. Generalizando este exemplo, Klee &
Minty (1972) construíram (para n = 2, 3,...) um PPL com n decisões variáveis e n
expressões para que o algoritmo s implex examinassem 2 n -1 soluções básicas viáveis antes
da solução ótima se descoberta. Assim, existe um PPL com 10 variáveis e 10 expressões
para que o simplex requeira 21 0 - 1= 1023 pivôs para descobrir a solução ótima. Assim
sendo, tão patológico PPL raramente ocorre em aplicações práticas.
Graficamente tem- se:

Pesquisa Operacional / Uma Introdução a Complexidade 22


As restrições representam uma distorção no hipercubo n- dimensional

O exemplo de Klee- Minty mostrou que:


Executaremos 2 n – 1 iterações para resolver um problema de n variá veis e restrições.
Para n = 70,
2n = 1.2 x 10 21 ,

Pesquisa Operacional / Uma Introdução a Complexidade 23


Em 1000 iterações por segundo, este problema levará 40 bilhões de anos para resolver. A
idade do universo é estimada em 15 bilhões de anos.
O método simplex:
• No pior caso: n2 2 n operações

• No caso médio: n3 operações


Questão: Existe uma variante do método simplex o qual no pior caso a performance é
polinomial?
• Teorema: Existe um algoritmo o performance no “pior caso” é n3 . 5 operações.

Pesquisa Operacional / Uma Introdução a Complexidade 24

Potrebbero piacerti anche