190 likes | 285 Views
Projeto de Programação PD-I. Caxeiro Viajante. Felipe Costa Corona Lucas Catabriga Rocha. Problema:.
E N D
Projeto de Programação PD-I Caxeiro Viajante Felipe Costa Corona Lucas Catabriga Rocha
Problema: Dado um número de cidades e o custo para ir de uma cidade qualquer para outra cidade qualquer, qual a rota com menor custo que visita todas as cidades exatamente uma vez e retorna ao ponto de partida?
O problema do caxeiro viajante é um problema NP-completo. Neste tipo de problema é fácil verificar uma solução para o problema, mas demorado para achar a solução do problema. Não existe na atualidade um algoritmo capaz de resolver este tipo de problema de forma eficiente. A maioria dos pesquisadores acreditam que uma solução eficiente não exista e que a única maneira de resolver o problema com certeza seja simplesmente testar todas as possibilidades.
O programa deve ser capaz de resolver o problema usando força bruta, que é testar todas as possibilidades. Como este método é apenas funcional para um número pequeno de cidades, deve também resolver o problema usando heurística, isto é, um algoritmo que da uma resposta rapidamente, porém sem garantias de que será a melhor resposta ou até mesmo uma boa resposta.
Para testar o programa será usada uma lista de cidades com tamanho arbitrário, para se testar até que número de cidades uma solução é eficiente, e algumas listas de cidades em que se conhece a melhor solução de vários tamanhos diferentes. Os resultados e custo computacional de cada algoritmo será comparado com os outros algoritmos para avaliar sua eficiência.
Força Bruta Neste método serão testados todos os caminhos possíveis, e se escolherá o melhor. Deve-se gerar todas as permutações possíveis, calcular a distância de cada um desses caminhos e escolher o menor. Uma função gera todas as permutações, quando as permutações são terminadas, calcula a distância de todos os caminhos e ordena a lista de caminhos baseado na distancia. Pega o caminho com a menor distância.
permut10 ls cs n listaP = if (length (fst (cs!!0)) < n) then permut10 ls [ (fst x ++ [y], delete y (snd x)) | x<-cs, y<-(snd x) ] n listaP else [ (distCaminho10 ls (caminho x) listaP, caminho x) | x<-cs, (fst x)!!1 last (fst x) ] where caminho x = fst x ++ ([head (fst x)]) distCaminho10 ls cs listaP = sum [((listaP)!!((cs!!(x))))!!((cs!!(x+1)))|x<-[0..((length cs)-2)]] caminhosPossiveis10 ls = sort (permut10 ls [([0],[1..((length ls)-1)])] (length ls) listaP10) where listaP10 = [[distC (ls!!x) (ls!!y)|y<[0..((length ls)-1)]]|x<-[0..((length ls)-1)]] menorCaminho10 ls = head (caminhosPossiveis10 ls)
Algoritmo do vizinho mais próximo Neste algoritmo, o caxeiro visita sempre a cidade mais próxima que ainda não visitou. Retorna um resultado muito mais rápido que o algoritmo de força bruta e na maioria das vezes tem um resultado razoável. Apesar disso, existem casos em que este algoritmo retorna o pior resultado possível ou simplesmente retorna respostas ruins.
cidadeProxima11 c ls fs listaP = snd (head (sort [(((listaP!!c)!!x),x)|x<-fs])) listaCaminho11 ls cs fs n listaP = if(length cs == 0) then listaCaminho11 ls [n] (delete (n) fs) n listaP else if(length fs >0) then listaCaminho11 ls (cs ++ [cidadeProxima]) (delete (cidadeProxima) fs) n listaP else cs where cidadeProxima = cidadeProxima11 (last cs) ls fs listaP distCaminho11 ls cs listaP = sum [((listaP)!!((cs!!(x))))!!((cs!!(x+1)))|x<-[0..((length cs)-2)]] caminho11 ls n = (distCaminho11 ls (menorCaminho) listaP11, menorCaminho) where listaP11 = [[distC (ls!!x) (ls!!y)|y<-[0..((length ls)-1)]]|x<-[0..((length ls)-1)]] listaCaminho = listaCaminho11 ls [] [0..((length ls)-1)] n listaP11 menorCaminho = (listaCaminho) ++ [head (listaCaminho)] menorCaminho11 ls = caminho11 ls 0
Algorimo de caminho sem cruzamentos Se acontecerem cruzamentos em um caminho, sempre que estes cruzamentos forem retirados, o caminho resultante será mais curto. Este algoritmo gera um caminho quase sempre sem cruzamentos acrescentando as cidades sempre na posição do caminho em que o custo será menor. O algoritmo pode ser melhorado, com um custo relativamente alto, para checar se no caminho final algumas cidades podem mudar de posição dentro da lista melhorando a eficiência ou até mesmo checar isto depois que cada cidade é acrescentada.
acrescimoDist7 ls c cs = [ ((newDist x) - (oldDist x), x)| x<-[0..((length cs)-2)] ] where newDist x = (distC (ls!!(cs!!x)) (ls!!c)) + (distC (ls!!(cs!!(x+1))) (ls!!c)) oldDist x = (distC (ls!!(cs!!x)) (ls!!(cs!!(x+1)))) menorAcrescimo7 ls c cs = head (sort (acrescimoDist7 ls c cs)) adicionarCidade7 ls c cs = (take (x+1) cs) ++ [c] ++ (drop (x+1) cs) where x = snd (menorAcrescimo7 ls c cs) criarCaminho7 ls es cs = if((length es)==1) then adicionarCidade7 ls (head es) cs else criarCaminho7 ls (tail es) (adicionarCidade7 ls (head es) cs) distCaminho7 ls cs = sum [distC (ls!!(cs!!(x))) (ls!!(cs!!(x+1)))|x<-[0..((length cs)-2)]] menorCaminho7 ls = ( distCaminho7 ls caminho,caminho) where caminho = criarCaminho7 ls [2..((length ls)-1)] [0,1,0]
Vizinho Melhor Cruzamento
50 cidades 1177.989 - (5798874 reductions, 7541514 cells, 1 garbage collection) 1137.771 - (31751768 reductions, 41143647 cells, 6 garbage collections) 1131.809 - (206467313 reductions, 269110913 cells, 41 garbage collections) 1299.104 - (2927819 reductions, 3790414 cells)
250 cidades 2517.298 - (872833096 reductions, 2269635550 cells, 1007 garbage collections) 2906.656 - (309180657 reductions, 392466969 cells, 61 garbage collections) 2592.589 - (619329632 reductions, 787694969 cells, 120 garbage collections) 2490.195 - (423.05 secs, 19997670984 bytes)
1500 cidades 7231.9097 - (105.38 secs, 1457987636 bytes) 6358.4644 - (218.69 secs, 4351012052 bytes) 6133.933 - (2849.63 secs, 49043462212 bytes)
Trajetos que se conhece o melhor caminho Cidades na África, 29 cidades, melhor caminho 27603: Vizinho: 36388.06 - (618427 reductions, 808761 cells) Cruzamento: 30082.69 - (1283666 reductions, 1695492 cells) Cruzamento +: 27601.17 - (6636799 reductions, 8722390 cells, 1 garbage collection) Cruzamento ++: 27601.17 - (28766053 reductions, 38049563 cells, 5 garbage collections)
Cidades Djibouti, 89 cidades, melhor caminho 6656: Vizinho: 8301.27376095897 - (14977253 reductions, 19229711 cells, 2 garbage collections) Cruzamento: 7526.87518340197 - (29853866 reductions, 38602696 cells, 5 garbage collections) Cruzamento +: 7526.87518340197 - (100537009 reductions, 129600341 cells, 19 garbage collections) Cruzamento ++:7339.69873526813 - (2987104522 reductions, 3866811319 cells, 593 garbage collections)
Cidades Luxemburgo, 980 cidades, melhor caminho 11340: Cidades Qatar, 194 cidades, melhor caminho 9352: Vizinho: 11892.888058614652 Cruzamento: 11745.371680332111 Cruzamento +: 10441.392017942579 Cruzamento ++: 10328.863282018918 Vizinho: 14212.721606057083 Cruzamento: 12493.614273875739 Cruzamento +: 12278.669597492893