• Nenhum resultado encontrado

Adjacência de Arestas Biobjetivo

2.5 Revisão da Literatura

Nessa seção serão explorados os trabalhos relacionados ao problema da AGQA-bi, destacando os algoritmos apresentados. Os trabalhos descritos compreendem abordagens (meta)heurísticas e exatas. Todavia, dado que o problema da AGQA-bi ainda não foi exaustivamente explorado, nenhum trabalho envolvendo hibridização de algoritmos exatos e meta-heurísticos foi encontrado na revisão da literatura.

2.5.1

Maia (2013)

2.5.1.1 Backtracking

Monteiro apresentou no ano de 2013, em sua tese de doutorado, o primeiro algoritmo exato, um backtracking, para o problema da AGQA-bi. O algoritmo proposto agrupa as arestas do grafo dado como entrada em três grupos I, O e L que definem as arestas que pertencem a solução corrente, as arestas que estão proibidas de entrar na solução corrente e as arestas que podem entrar na solução, respectivamente. Desse modo, realizar uma busca no grafo implícito do backtracking nada mais é do que realizar operações (inserção e remoção) sobre os grupos I, O e L. No algoritmo, cada bifurcação realizada na busca, considera a inserção de uma determinada aresta em I, configurando um caminho possível, e inserindo em O, configurando o outro caminho. As estruturas de dados utilizadas foram, lista de arestas para representar o grafo e as soluções do problema, bem como as arestas que podem estar na solução corrente, ou seja, listaL e listaI. Também é utilizado uma pilha, denominada pilhaO, para representar as arestas que estão proibidas de entrar na solução. No entanto, na pilhaO cada elemento além de armazenar uma aresta armazena também o nível do grafo implícito no qual a aresta foi inserida ou removida da solução.

O algoritmo inicializa listaL e pilhaO vazios, e todas as arestas do grafo são inseridas em listaL. Posteriormente são geradas soluções iniciais para o conjunto de soluções não- dominadas usando uma escalarização da heurística H2 apresentada por (ASSAD; XU, 1992). A cada iteração do algoritmo uma aresta de listaL é avaliada para entrar em listaI, ou seja, compor a solução parcial. Caso essa aresta não induza um ciclo ela é então removida de listaL e inserida em listaI, e em pilhaO, uma vez que ela já faz parte da solução e não pode mais fazer parte das arestas que podem entrar. A autora utiliza a estrutura de dados Union Find (CORMEN, 2009) para verificar a ocorrência de ciclo. Esse procedimento continua até que listaI tenha n − 1 arestas, quando isso ocorre a solução e então adicionada ao conjunto de soluções não-dominadas. Caso a solução gerada já for dominada por alguma outra solução, então ela é excluída e se a solução gerada dominar alguma outra solução no conjunto de soluções não-dominadas, tal solução dominada deve ser removida do conjunto.

Ademais, cada vez que uma aresta é inserida na solução parcial verifica-se se a própria solução parcial já é dominada por alguma solução no conjunto de soluções não-dominadas. Se esse for o caso, essa aresta deve ser removida da solução parcial e a busca no ramo do grafo implícito, que tem raiz na solução parcial anterior, deve ser abandonada.

O algoritmo encerra quando nenhuma nova árvore pode ser gerada, ou seja, quando listaL está vazia e todas as outras possibilidades de árvores já foram verificadas. No que segue, o backtracking proposto é apresentado abaixo no Algoritmo 1.

Algoritmo 1: Backtracking – Maia 2013 Entrada: G = (V, E)

1 início

2 Adicione todas as arestas de G à ListaL 3 Inicie sol com uma árvore vazia

4 Inicie pilhaO também vazia

5 Inicie P aretoF ront com soluções da heurística H2 escalarizada 6 end ← f also e tamSolAtual ← 0

7 enquanto !end faça

8 e ← listaL.primeiroElemento()

9 se e não existe porque ListaL está vazia então 10 se tamSolAtual = 0 então

11 end ← verdadeiro 12 senão

13 Retire de pilhaO os elementos associados com tamSolAtual 14 Reinsira tais elementos em listaL

15 tamSolAtual ← tamSolAtual − 1

16 Atualize o valor função-objetivo (parcial) de sol 17 fim

18 senão se a inserção de e em sol não gerar ciclo então 19 sol[tamSolAtual] ← e

20 Adicione (e, tamSolAtual) à pilhaO 21 Remova e de listaL

22 Atualize o valor da função-objetivo (parcial) para sol 23 se sol corresponde a uma árvore completa então 24 Atualize P aretoF ront de acordo com sol

25 senão se a função-objetivo parcial de sol já é dominada por alguma

solução em ParetoSet então

26 Não atualize tamSolAtual

27 Atualize o valor da função-objetivo (parcial) de sol de forma a

excluir e

28 senão

29 tamSolAtual ← tamSolAtual + 1 30 fim

31 senão

32 Adicione (e, tamSolAtual) a pilhaO 33 Remova e de listaL

34 fim 35 fim 36 fim

2.5.1.2 Branch-and-Bound

Em 2013 a autora de (MAIA, 2013) apresentou um algoritmo exato utilizando a técnica de branch-and-Bound para o problema da AGQA-bi. O algoritmo teve como base o algo- ritmo de backtracking, desenvolvido pela autora no mesmo trabalho, todavia adicionando podas no grafo implícito, por meio de limites superiores e inferiores, reduzindo assim o espeço de busca e informando quais ramos tem prioridade na exploração da busca.

No cenário multiobjetivo, os limites superiores e inferiores são, respectivamente, a melhor solução (conjunto de soluções não-dominadas) encontrada durante a execução do algoritmo, e uma estimativa da melhor solução que pode ser encontrada considerando as arestas que já fazem parte da solução parcial. Vale ressaltar que o limite inferior deve ser, garantidamente, melhor ou no máximo igual a real melhor solução que pode ser encontrada.

Sendo assim, no algoritmo proposto, a poda do grafo implícito ocorre quando o valor do limite inferior já é dominado pelo limite superior, em outras palavras, não é possível encontrar uma solução melhor, a partir do ramo analisado, que a melhor solução já en- contrada, por conseguinte a busca nesse ramo deve ser abandonada, fazendo com que esse ramo não seja mais explorado desnecessariamente.

O limite inferior adotado pela autora é uma adaptação do limite apresentado por (ASSAD; XU, 1992) para o problema da AGMQA. O limite que a autora propôs, é pois, um par ordenado, no qual a primeira componente diz respeito aos custos lineares das arestas, que é calculado utilizando uma adaptação do algoritmo de Kruskal para a AGM, no qual as arestas que já compõem a solução parcial são mandatórias. No que diz respeito a segunda componente, ou seja, os custos quadráticos esse valor também é calculado utilizando o algoritmo de Kruskal adaptado considerando as arestas que já fazem parte da solução. Todavia, os custos considerados pelo algoritmo para montar a árvore são dados pela seguinte Equação 2.12.

lbi =    min{cij|j ∈ Li} , se I ∩ Ai = ∅ P

j∈I(cij + cji) , outros casos

(2.12)

Como dito anteriormente o algoritmo desenvolvido é baseado no backtracking da mesma autora, sendo assim ele utiliza as mesmas estruturas para realizar a busca no grafo implícito, ou seja, nas listas listaL e listaI bem como pilhaO. Tais estruturas fun- cionam de acordo como é descrito no algoritmo backtracking. A diferença fundamental

acontece quando se insere uma nova aresta na solução parcial e a mesma não se torna completa, nesse caso o valor do limite inferior é calculado, e caso ele seja dominado pelo limite superior esse ramo também é descartado da busca. O Algoritmo 2 apresenta o branch-and-bound desenvolvido.

Algoritmo 2: Branch-and-Bound – Maia 2013 Entrada: G = (V, E)

1 início

2 Adicione todas as arestas de G à ListaL 3 Inicie sol com uma árvore vazia

4 Inicie pilhaO também vazia

5 Inicie P aretoF ront com soluções da heurística H2 escalarizada 6 end ← f also e tamSolAtual ← 0

7 lb ← CalculeLimiteInferior (sol) 8 enquanto !end faça

9 e ← Aresta de listaL com menor valor de lbi 10 se e não existe porque ListaL está vazia então 11 se tamSolAtual = 0 então

12 end ← verdadeiro 13 senão

14 Retire de pilhaO os elementos associados com tamSolAtual 15 Reinsira tais elementos em listaL

16 tamSolAtual ← tamSolAtual − 1 17 fim

18 senão se a inserção de e em sol não gerar ciclo então 19 sol[tamSolAtual] ← e

20 Adicione (e, tamSolAtual) à pilhaO 21 Remova e de listaL

22 se sol corresponde a uma árvore completa então 23 Calcule o valor da função-objetivo para sol 24 Atualize P aretoF ront de acordo com sol 25 senão

26 lb ← CalculeLimiteInferior (sol) 27 Não atualize tamSolAtual

28 se ParetoFront.Domina(lb) for falso então 29 tamSolAtual ← tamSolAtual + 1 30 fim

31 Atualize o valor da função-objetivo (parcial) de sol de forma a

excluir e

32 senão

33 tamSolAtual ← tamSolAtual + 1 34 fim

35 senão

36 Adicione (e, tamSolAtual) a pilhaO 37 Remova e de listaL

38 fim 39 fim 40 fim

2.5.1.3 Pareto Local Search

Em (MAIA, 2013), a autora apresenta um algoritmo de Busca Local de Pareto (Pareto Local Search, em inglês) (PLS) para o problema da AGQ-bi. Tal algoritmo funciona da seguinte forma. Inicialmente é gerada uma solução, sol, escolhendo cada aresta que irá compor a solução de maneira aleatória.

Uma vez que a solução inicial tenha sido construída, tal solução é incluída no conjunto de soluções não dominadas, conjSN D, e marcada como não explorada. Um procedimento iterativo é então iniciado. A cada iteração, uma solução pertencente a conjSN D é esco- lhida para ser explorada. A partir daí a vizinhança da solução escolhida é gerada como uma busca ejection chain.

Esse procedimento funciona em dois laços, o mais externo é executado um número maxT ent vezes. A cada iteração desse laço, a solução escolhida no passo anterior é sub- metida a um vetor de escalarização escolhido aleatoriamente. No que segue, no laço mais interno, a aresta com maior contribuição para o custo total da árvore é removida, então tenta-se inserir a aresta, que ainda não faz parte da solução, que tiver menor contribuição para o custo da árvore, e que obviamente, não gere um ciclo.

A nova solução é submetida ao conjSN D, caso ela não seja dominada por alguma solução então ela deve ser inserida em conjSN D, e caso ela domine alguma solução de conjSN D tal solução dominada deve ser removida.

Quando todas soluções de conjSN D estiverem marcadas como exploradas o algoritmo termina. O pseudo-código do algoritmo proposto segue abaixo (Algoritmo 3).

Algoritmo 3: Pareto Local Search – Maia 2013

1 início

2 π ← Solução gerada aleatoriamente 3 visitado (solπ) ← f also

4 listaSN D ← solπ

5 enquanto ∃u ∈ listaSN D | visitado (u) = falso faça

6 Escolher uma solução qualquer u ∈ listaSN D | visitado (u) = f also 7 para todo α ∈ V izinhos(u) faça

8 se não existe solução em listaSN D que domine α então 9 visitado(α) ← f also

listaSN D ← {listaSN D − {β ∈ listaSN D | α domina β}} ∪ α

10 fim 11 fim 12 visitado(u) ← verdadeiro 13 fim 14 fim 15 retorna listaSND 2.5.1.4 Busca Tabu

Em 2013, a autora de (MAIA, 2013) apresentou um algoritmo Busca Tabu para o problema da AGQA-bi. Tal algoritmo funciona da seguinte maneira.

A primeira etapa, a geração da população inicial, acontece por meio da heurística H1 de (ASSAD; XU, 1992), escalarizada, auxiliada por um pré-processamento.

Uma vez que as soluções iniciais tenham sido criadas, o algoritmo segue, a cada iteração, visitando uma solução em busca de algum vizinho que minimize a função objetivo do problema, sujeita a um vetor de escalarização previamente selecionado, e que não configure um movimento tabu.

O critério de aspiração utilizado é referente a não-dominância, isto é, caso a solução vi- zinha encontrada seja não-dominada com relação ao conjunto de aproximação arquivado, a mesmo deve ser inserida no conjunto, mesma que configure um movimento Tabu. O mé- todo de geração da vizinhaça adotado pela autora é semelhante ao utilizado no algoritmo PLS com ejection chain apresentado no mesmo trabalho. Segue abaixo, no Algoritmo 4, o pseudo-código da Busca Tabu proposta.

Algoritmo 4: Busca Tabu - Maia 2013

1 CriarConjuntoInicial(conj[TAMCONJ]) 2 para itr ← até NUMITER faça

3 para i ← 1 até TAMCONJ faça

4 gerarVizinhosEjectionChain(pop[i],i,itr)

5 se critério de diversficação for satisfeito então 6 conj[i] ← Solução aleatória pertence listaSND 7 fim

8 fim 9 fim

2.5.2

Pinheiro (2016)

2.5.2.1 Backtracking

O algoritmo de backtracking proposto por (PINHEIRO, 2016) é bastante simples e tem o propósito de demonstrar a aplicação da técnica de backtracking no problema da AGQA-bi. A estrutura de dados utilizada neste trabalho para representar o grafo, foi uma lista de arestas, no entanto o autor sempre as mantinha ordenadas pelo custo linear. A técnica empregada visa identificar quais combinações de arestas geram uma árvore sem, no entanto, explicitamente gerar todas as árvores possíveis para o grafo dado como entrada do algoritmo. O autor também mantém uma lista com os índices das arestas que já fazem parte da solução parcialmente construída, denominada sol, bem como uma variável, currEdge, que informa a última aresta analisada no grafo de entrada. O algoritmo então, recursivamente, verifica se a inserção da aresta indicada por currEdge induz um ciclo na solução parcial construída até então. Se a aresta não gerar um ciclo, o processo se repete até que a árvore esteja completa, ou seja, assim que a solução tenha n − 1 arestas, onde n é o número de vértices do grafo. Nesse ponto é verificado se a solução construída já é dominada por alguma outra árvore armazenada no conjunto de soluções não-dominadas, isto é, na aproximação da Fronteira de Pareto e saída do algoritmo. Se esse for o caso, esse ramo do grafo implícito é descartado da busca e acontece o processo de backtracking. Caso contrário continua-se a exploração no grafo implícito por novas soluções, considerando também a não inserção da aresta indicada por currEdge. O autor utiliza a estrutura de dados Union-Find para verificar a existência de ciclos. A seguir o Algoritmo 5 exibe o funcionamento do backtracking proposto.

Algoritmo 5: Backtracking - Pinheiro 2016 Entrada: edges, pos, sol, n, m, U nionF ind

Saída: Um conjunto de soluções não-dominadas, P aretoF ront

1 início

2 se | sol | = n-1 então

3 se sol não for dominada por alguém em ParetoFront então 4 P aretoF ront ← P aretoF ront ∪ {sol}

5 se sol domina alguém em ParetoFront então 6 exclua as solução dominadas por sol. 7 fim

8 senão 9 encerre 10 fim

11 senão

12 para i = pos até m - | sol | faça

13 se UnionFind.busca(edges[ i ].v1) != UnionFind.busca(edges[ i ].v2)

então

14 U nionF ind.uniao(edges[ i ] ) 15 sol ← sol ∪ {edges[i]}

16 Backtracking(edges, i + 1, sol, n, m, U nionF ind) 17 sol ← sol / {edges[i]}

18 fim 19 fim 20 fim 21 fim

22 retorna P aretoF ront

2.5.2.2 Branch-and-Bound

O algoritmo de branch-and-bound proposto por (PINHEIRO, 2016) tem como base o backtracking proposto no mesmo trabalho. Neste algoritmo são adicionados cálculos de limites inferiores e superiores. Tais cálculos visam estimar o custo, tanto do objetivo linear quanto do quadrático, considerando que algumas arestas são mandatórias, ou seja, as que já fazem parte da solução parcial. Esses limites servem para estimar qual a melhor solução possível a ser encontrada considerando as arestas mandatórias. Vale ressaltar que

os valores obtidos a partir do cálculo dos limites inferiores podem resultar em soluções que de fato não existem. Todavia qualquer solução viável que pode ser encontrada a partir daquele nó do grafo implícito deve necessariamente ser dominada por esses valores. No contexto multiobjetivo o limite superior é simplesmente o conjunto de soluções não- dominadas encontradas pelo algoritmo até o momento.

Os limites têm papel fundamental na redução do espaço de busca, podando o grafo implícito, indicando quais ramos não podem levar a uma solução ótima. A utilização dos limites dar-se-á da seguinte maneira. Uma vez calculado ambos os limites, os mesmos são comparados. Se o limite inferior for dominado por alguma solução do limite superior, então esse ramo não deve mais ser explorado, pois nenhuma solução com melhor valor que o limite inferior pode ser encontrada, e qualquer solução encontrada já será dominada pelo limite superior. Desse modo, quanto melhor for a estimativa do limite inferior mais podas serão realizadas e por consequência menor será o espaço de busca a ser explorado. Para calcular o limite inferior o autor usou a seguinte estratégia. Para a estimativa linear calcula-se a árvore geradora mínima ponderando o custo quadrático por zero e mantendo as arestas da solução parcial como mandatórias. Para a estimativa do custo quadrático insere-se as arestas que menos contribuem para o custo total, ponderando o custo linear por zero assim como na estimativa linear. E também como na estimativa linear, as arestas que se encontram na solução parcial são mandatórias. Ambos os cálculos consideram que a lista de arestas está inicialmente ordenada pelo custo linear. O autor faz ainda uma ressalva para quando não é possível construir uma árvore a partir do nó explorado, nesse caso o custo das estimativas terá um valor negativo. Quando essa situação acontece esse ramo também deve ser descartado da busca uma vez que não será possível obter uma solução a partir dele. O algoritmo de branch-and-bound desenvolvido segue abaixo, Algoritmo 6.

Algoritmo 6: Branch-and-Bound - Pinheiro 2016 Entrada: edges, pos, sol, n, m, U nionF ind

Saída: Um conjunto de soluções não-dominadas, P aretoF ront

1 início

2 se | sol | = n-1 então

3 se sol não for dominada por alguém em ParetoFront então 4 P aretoF ront ← P aretoF ront ∪ {sol}

5 se sol domina alguém em ParetoFront então 6 exclua as solução dominadas por sol. 7 fim

8 senão 9 encerre 10 fim

11 senão

12 para i = pos até m - | sol | faça

13 se UnionFind.busca(edges[ i ].v1) != UnionFind.busca(edges[ i ].v2)

então

14 U nionF ind.uniao(edges[ i ] ) 15 sol ← sol ∪ {edges[i]}

16 limite ← {estimativaLinear(), estimativaQuadratica} 17 se limite não for diminado por alguém de ParetoFront então 18 Branch-and-Bound(edges, i + 1, sol, n, m, U nionF ind) 19 fim

20 sol ← sol / {edges[i]} 21 fim

22 fim 23 fim 24 fim

25 retorna P aretoF ront

2.5.2.3 Pareto Local Search

O algoritmo de Pareto Local Search (PLS) proposto por (PINHEIRO, 2016) é uma variante do apresentado por (MAIA, 2013) diferindo essencialmente na estrutura de vi- zinhança utilizada e no método de inicialização do algoritmo, ou seja, na geração das

soluções não-dominadas iniciais. No começo, gera-se apenas uma solução da seguinte ma- neira. Embaralha-se as arestas do grafo dado como entrada, representado neste trabalho como uma lista de arestas, a partir daí utiliza-se uma estratégia semelhante ao algoritmo de Kruskal (KRUSKAL, 1956), selecionando arestas que não induzem um ciclo até que a solução esteja completa. Essa solução é então marcada como não explorada e incluída no conjunto de soluções não-dominadas.

O processo seguinte constitui-se em sistematicamente verificar cada solução não ex- plorada do conjunto de aproximação da Fronteira de Pareto. Sendo assim, uma solução é selecionada e sua vizinhança é então gerada. No que segue, a estrutura de vizinhança adotada consiste em todas as árvores formadas pela inserção de uma aresta que não faz parte da solução corrente e pela retirada de cada aresta que faz parte do ciclo gerado pela inclusão da aresta selecionada.

Em seguida, de posse da vizinhança da solução selecionada, cada solução da vizinhança que é não-dominada com relação a solução selecionada se torna candidata a fazer parte do conjunto de soluções não-dominadas. É verificado então, para cada solução da vizinhança, se a mesma já é dominada por alguma solução do conjunto de soluções não-dominadas, se isso de fato for o caso então essa solução é descartada. Caso contrário, remove-se do conjunto de soluções não-dominadas todas as soluções que porventura sejam dominadas pela solução avaliada e por fim adiciona-se a solução candidata ao conjunto. Ao final desse passo a solução escolhida para gerar a vizinhança é marcada como explorada. O algoritmo encerra quando todas as soluções forem exploradas. Abaixo o Algoritmo 7 resume o procedimento proposto.

Ainda foram propostas algumas variações da PLS no mesmo trabalho de (PINHEIRO, 2016) que se diferenciam fundamentalmente no método de geração das soluções não- dominadas iniciais. Os métodos utilizados foram: heurística H2 de (ASSAD; XU, 1992) com tamanho do conjunto de soluções iniciais fixo e heurística H2 com tamanho aleatório do conjunto. Foi também proposta uma variante na qual a solução a ser explorada é escolhida de forma aleatória. Foi apresentado também um algoritmo que o autor denominou de PLS-GRASP no qual difere na geração da vizinhança utilizada nos demais algoritmos apresentados da seguinte maneira: dado que uma solução foi escolhida para ser explorada, um subconjunto das arestas que não fazem parte da solução visitada é tomado e para cada aresta desse subconjunto é aplicada a mesma estratégia já descrita para os demais algoritmos.

Algoritmo 7: PLS - Pinheiro 2016 Entrada: edges, n, m 1 ConjuntoDisjunto tree; 2 Conjunto Fronteira; 3 Solução atual; 4 embaralhar(edges);

5 para i variando de 0 até m-1 faça

6 se tree.find(edges[i].v1)!= tree.find(edges[i].v2 então 7 tree.uniao(edges[i]); 8 atual.adicionar(edges[i]); 9 fim 10 fim 11 atual.visitado = falso; 12 fronteira.adicionar(atual);

13 enquanto Não houver soluções visitadas na fronteira faça

14 Solução sol = solução não visitada em fronteira; para i de 0 até m-1 faça 15 se edges[i] não faz parte de sol então

16 vectorharestai ars ← arestasNoCaminho(edges[i].v1, edges[i].v2); 17 para j de 0 até ars.tamanho()-1 faça

18 Solução aux ← sol ars[j] ∪ edges[i];

19 se aux não for dominada por outra solução em fronteira então 20 aux.visitada = falso;

21 fronteira.adicionar(aux);

22 remover soluções dominadas por aux de fronteira; 23 fim

24 fim 25 fim

26 se ainda fizer parte da fronteira então 27 sol.visitada = verdadeiro;

28 fim 29 fim

2.5.2.4 GRASP

Na sua dissertação de mestrado (PINHEIRO, 2016) descreve um algoritmo Greedy Ran- domized Adaptive Search Procedure (GRASP) para o problema da AGQA-bi. O algoritmo descrito é composto de duas fases uma de construção da solução, a partir de um procedi- mento semi-guloso adaptativo, e uma outra fase de busca local.

O procedimento de construção da solução funciona como se segue. Primeiramente ordenam-se as arestas do grafo dado como entrada de acordo com o custo linear de cada aresta. Em seguida um rank é atribuído a cada aresta, que nada mais é do que a sua posição na lista arestas ordenadas, ou seja, a aresta com menor custo linear associado

Documentos relacionados