• Nenhum resultado encontrado

Algoritmo 16 – Variable Neighborhood Search (VNS)

3.1 Métodos exatos

Para resolver de forma exata o PCV-PL e assim determinar as soluções ótimas das instâncias artificiais criadas, foram utilizadas três técnicas distintas. Primeiramente, foi utilizado um algoritmo Branch-and-bound especificamente concebido para o PCV-PL. Posteriormente, foi aplicada a solução por Programação Matemática. Por fim, foi investigada a Programação por Restrições.

3.1.1 Branch-and-bound

O método clássico Branch-and-bound, comumente empregado na solução de problemas de otimização combinatória de alta complexidade, coloca-se como alternativa inteligente à enumeração extensiva de soluções na busca pela melhor delas. A técnica pode ser vista como uma forma de sistematicamente analisar o espaço de soluções tomando por base um grafo acíclico direcionado costumeiramente denominado como árvore de busca. Via de regra, tal grafo é implementado como grafo implícito, ou seja, seus vértices e arestas não são criados como objetos que ocupam espaço na memória de um computador, mas sim, como elementos que surgem como consequência dos passos do algoritmo. Os nós do grafo representam decisões e são efetuadas avaliações a cada decisão tomada, sendo a sequência interrompida quando não há mais decisões possíveis, e aquele ramo é declarado insolúvel, ou foi encontrada uma sequência de decisões que representam uma solução viável para o problema.

A eficiência do método deve-se à capacidade de prematuramente eliminar soluções que ainda estão em construção mas que já demonstram sua incapacidade de apresentarem qualidade superior a uma solução previamente conhecida. Baseia-se, de forma geral, em dois processos: o branch, que atua dividindo o espaço de soluções e deve fazê-lo da maneira mais eficiente e com a maior granularidade possível, e o bound, que consiste na avaliação de uma solução parcial com base em cálculos de limites inferiores e superiores referentes ao custo de soluções. O mecanismo por trás de um bom procedimento branch deve adicionar gradualmente componentes a uma solução parcial de modo que esta vai se tornando cada vez mais próxima de uma solução completa. O procedimento bound, por sua vez, exige que os cálculos dos limites sejam determináveis eficientemente de modo que não haja competição entre os custos

computacionais para estes cálculos e a enumeração de fato. O limite superior é dado pelo valor de uma solução já conhecida, enquanto que o limite inferior é uma estimativa matemática para o custo mínimo de soluções completas que venham a surgir como evolução da solução parcial atualmente em construção. No algoritmo, estes dois mecanismos atuam de forma combinada, e a cada branch é feito o bound, sendo calculados os limites. Se, para um nó, o limite inferior é maior que o limite superior, a formação da solução é interrompida pois foi encontrado um ramo sem possibilidade de obter solução melhor que a conhecida. Caso contrário, os nós são desenvolvidos na ordem crescente dos seus limites inferiores, uma vez que um menor limite inferior expressa um caminho mais promissor para a exploração.

O Branch-and-bound é, via de regra, implementado utilizando-se do artifício da recursividade, sendo aplicado quando não se conhece um outro método eficiente para encontrar a solução exata. Uma vez que está sendo abordado um novo problema, trata-se de uma escolha adequada.

3.1.2 Programação Matemática

A Programação Matemática (Mathematical Programming) abrange a Programação Linear, a Programação Não Linear, Programação Inteira, Programação Dinâmica, Programação Geométrica e a Programação Estocástica. Trata-se, atualmente, do método de preferência para determinação de soluções exatas para problemas de otimização combinatória de considerável complexidade computacional. Requer o desenvolvimento prévio de um modelo matemático que siga diretrizes da programação linear, embora aceite, em geral, restrições ou objetivos com característica não linear. Em linhas gerais, a programação matemática pode ser encarada como uma extensão da programação linear.

Em geral, todo problema de programação linear é um problema de otimização uma vez que procura a solução de melhor qualidade segundo um critério pré-estabelecido. Segundo (BRONSON; NAADIMUTHU, 1997), enquadram-se nessa categoria os problemas com as seguintes características:

• Existe um conjunto de variáveis manipuláveis no procedimento de solução: são as variáveis de decisão do problema.

• O critério de qualidade é composto pela função objetivo, que é descrita em função das variáveis de decisão. Tal função é combinação linear das variáveis, podendo ser maximizada ou minimizada.

• As variáveis de decisão submetem-se, ainda, a critérios restritivos ou conjuntos de restrições, as quais compõem a região de soluções viáveis do problema. Tais variáveis podem também estar submetidas a regras que limitem os valores a subdomínios específicos dos números reais. Via de regra, a implementação de fato da busca por soluções ótimas com a programação matemática é feita com o uso de solvers com suporte à modelos matemáticos, como por exemplo (GUROBI, 2016), MATLAB e Couenne.

3.1.3 Programação por Restrições

Possui razoável semelhança com a programação matemática, uma vez que um modelo matemático é, em última análise, um conjunto de restrições. Além disso, ocupa uma posição sutilmente intermediária entre duas estratégias: uma concebida especificamente para um dado problema, como por exemplo um algoritmo branch-and-bound, e uma que se baseie puramente na solução de um modelo matemático. Em outras palavras, há mais liberdade na definição das restrições do problema em si e na forma como a busca pelo ótimo será realizada. Tal característica possibilita, por vezes, a elaboração de modelos bastante concisos e, em alguns casos, tempos computacionais comparáveis a técnicas utilizadas com mais frequência.

É pré-requisito para a utilização desta técnica o aprendizado de linguagens muitas vezes específicas aos solvers de programação por restrição, ou pelo menos, de alguma linguagem que ofereça um tradutor que seja interpretado pelo programa. Como exemplos de solvers de programação por restrições estão (GECODE, 2016), Google OR-tools e Chuffed. Note-se que, via de regra, um solver por restrições é capaz de solucionar modelos matemáticos formais.

Documentos relacionados