Como os fornecedores de mapas (como Google ou Yahoo! Maps) sugerem instruções?
Quero dizer, eles provavelmente têm dados do mundo real de alguma forma, certamente incluindo distâncias, mas também coisas como velocidades de condução, presença de calçadas, horários de trens etc. Mas suponha que os dados estejam em um formato mais simples, digamos um gráfico direcionado muito grande com pesos nas arestas refletindo distâncias. Quero poder calcular rapidamente direções de um ponto arbitrário para outro. Às vezes, esses pontos ficam próximos (dentro de uma cidade), enquanto às vezes ficam distantes (cross-country).
Algoritmos de gráficos como o algoritmo de Dijkstra não funcionarão porque o gráfico é enorme. Felizmente, algoritmos heurísticos como A * provavelmente funcionarão. No entanto, nossos dados são muito estruturados e talvez algum tipo de abordagem em camadas possa funcionar? (Por exemplo, armazene direções pré-computadas entre determinados pontos "principais", bem como algumas direções locais. Em seguida, as direções para dois pontos distantes envolverão direções locais para um ponto principal, direções globais para outro ponto principal e, em seguida, local instruções novamente.)
Quais algoritmos são realmente usados na prática?
PS. Essa pergunta foi motivada por encontrar peculiaridades nas direções do mapeamento on-line. Ao contrário da desigualdade do triângulo, às vezes o Google Maps acha que o XZ leva mais tempo e é mais longe do que usar um ponto intermediário como no XYZ . Mas talvez as direções a pé também sejam otimizadas para outro parâmetro?
PPS. Aqui está outra violação da desigualdade do triângulo que sugere (para mim) que eles usem algum tipo de abordagem em camadas: XZ versus XYZ . O primeiro parece usar o famoso Boulevard de Sebastopol, embora esteja um pouco fora do caminho.
Editar : nenhum desses exemplos parece funcionar mais, mas ambos funcionavam no momento da postagem original.
Respostas:
Falando como alguém que passou 18 meses trabalhando em uma empresa de mapeamento, que incluiu o trabalho no algoritmo de roteamento ... sim, o Dijkstra's funciona, com algumas modificações:
Com modificações nesse sentido, você pode fazer o roteamento até os países em um prazo bastante razoável.
fonte
Esta questão tem sido uma área ativa de pesquisa nos últimos anos. A idéia principal é fazer um pré - processamento no gráfico uma vez , para acelerar todas as consultas a seguir . Com essas informações adicionais, os itinerários podem ser calculados muito rapidamente. Ainda assim, o algoritmo de Dijkstra é a base para todas as otimizações.
Aracnídeo descreveu o uso de pesquisa bidirecional e remoção de borda com base em informações hierárquicas. Essas técnicas de aceleração funcionam muito bem, mas os algoritmos mais recentes superam essas técnicas em todos os aspectos. Com os algoritmos atuais, os caminhos mais curtos podem ser calculados em menos tempo do que um milissegundo em uma rede rodoviária continental. Uma implementação rápida do algoritmo não modificado do Dijkstra precisa de cerca de 10 segundos .
O artigo Algoritmos de planejamento de rota rápida de engenharia fornece uma visão geral do progresso da pesquisa nesse campo. Veja as referências desse documento para mais informações.
Os algoritmos conhecidos mais rápidos não usam informações sobre o status hierárquico da estrada nos dados, ou seja, se é uma estrada ou uma estrada local. Em vez disso, eles calculam em uma etapa de pré-processamento uma hierarquia própria que foi otimizada para acelerar o planejamento de rotas. Essa precomputação pode ser usada para podar a pesquisa: Longe do início e do destino, as estradas lentas não precisam ser consideradas durante o algoritmo de Dijkstra. Os benefícios são um desempenho muito bom e uma garantia de correção para o resultado.
Os primeiros algoritmos de planejamento de rota otimizados lidavam apenas com redes rodoviárias estáticas, o que significa que uma margem no gráfico tem um valor de custo fixo. Isso não é verdade na prática, pois queremos levar em consideração informações dinâmicas, como engarrafamentos ou restrições dependentes de veículos. Os algoritmos mais recentes também podem lidar com esses problemas, mas ainda existem problemas a serem resolvidos e a pesquisa está em andamento.
Se você precisar das distâncias mais curtas do caminho para calcular uma solução para o TSP , provavelmente está interessado em matrizes que contêm todas as distâncias entre suas fontes e destinos. Para isso, você pode considerar Computar os caminhos mais curtos de muitos para muitos usando hierarquias de rodovias . Observe que isso foi aprimorado pelas abordagens mais recentes nos últimos 2 anos.
fonte
Apenas abordando as violações da desigualdade do triângulo, espero que o fator extra para o qual eles estejam otimizando seja o senso comum. Você não quer necessariamente o caminho mais curto ou mais rápido, pois pode levar ao caos e destruição . Se você deseja que suas direções prefiram as principais rotas que são adequadas para caminhões e podem lidar com o envio de todos os motoristas que seguem por sat-nav, você rapidamente descarta a desigualdade do triângulo [1].
Se Y for uma rua residencial estreita entre X e Z, provavelmente você só deseja usar o atalho via Y se o usuário solicitar explicitamente XYZ. Se pedirem o XZ, devem seguir as principais estradas, mesmo que seja um pouco mais longe e demore um pouco mais. É semelhante ao paradoxo de Braess - se todos tentarem seguir o caminho mais curto e mais rápido, o congestionamento resultante significa que não é mais o caminho mais rápido para ninguém. A partir daqui, passamos da teoria dos grafos para a teoria dos jogos.
[1] De fato, qualquer esperança de que as distâncias produzidas sejam uma função de distância no sentido matemático morre quando você permite estradas de mão única e perde o requisito de simetria. Perder a desigualdade do triângulo também é apenas esfregar sal na ferida.
fonte
Aqui estão os algoritmos de roteamento mais rápidos do mundo, comparados e comprovados quanto à correção:
http://algo2.iti.uka.de/schultes/hwy/schultes_diss.pdf
Aqui está uma palestra do google tech sobre o assunto:
http://www.youtube.com/watch?v=-0ErpE8tQbw
Aqui está uma implementação do algoritmo de hierarquias de rodovias, conforme discutido por schultes (atualmente apenas em Berlim, estou escrevendo a interface e uma versão móvel também está sendo desenvolvida):
http://tom.mapsforge.org/
fonte
Eu não trabalhei no Google, Microsoft ou Yahoo Maps antes, então não posso dizer como eles funcionam.
No entanto, eu projetei um sistema personalizado de otimização da cadeia de suprimentos para uma empresa de energia que incluía um aplicativo de agendamento e roteamento para sua frota de caminhões. No entanto, nossos critérios de roteamento eram muito mais específicos do negócio do que onde a construção ou o tráfego diminuem ou o fechamento das faixas.
Empregamos uma técnica chamada ACO (Otimização de colônias de formigas) para agendar e encaminhar caminhões. Essa técnica é uma técnica de IA aplicada ao problema do vendedor ambulante para resolver problemas de roteamento. O truque com o ACO é criar um cálculo de erro com base em fatos conhecidos do roteamento, para que o modelo de solução de gráficos saiba quando sair (quando o erro é pequeno o suficiente).
Você pode pesquisar no Google ACO ou TSP para saber mais sobre essa técnica. No entanto, eu não usei nenhuma das ferramentas de IA de código aberto para isso, então não posso sugerir uma (embora eu tenha ouvido falar que o SWARM era bastante abrangente).
fonte
Esse argumento não se aplica necessariamente porque o Dijkstra geralmente não olha o gráfico completo, mas apenas um subconjunto muito pequeno (quanto melhor o gráfico interconectado, menor o subconjunto).
Dijkstra pode realmente ter um bom desempenho em gráficos bem comportados. Por outro lado, com uma parametrização cuidadosa, o A * sempre terá um desempenho tão bom ou melhor. Você já tentou o desempenho dos seus dados?
Dito isto, eu também ficaria muito interessado em ouvir sobre as experiências de outras pessoas. Obviamente, exemplos importantes como a pesquisa do Google Map são particularmente interessantes. Eu poderia imaginar algo como uma heurística do vizinho mais próximo.
fonte
O estado da arte atual em termos de tempos de consulta para redes rodoviárias estáticas é o algoritmo de rotulagem de Hub proposto por Abraham et al. http://link.springer.com/chapter/10.1007/978-3-642-20662-7_20 . Uma pesquisa completa e excelentemente escrita do campo foi publicada recentemente como um relatório técnico da Microsoft http://research.microsoft.com/pubs/207102/MSR-TR-2014-4.pdf .
A versão curta é ...
O algoritmo de rotulagem do Hub fornece as consultas mais rápidas para redes rodoviárias estáticas, mas requer uma grande quantidade de RAM para executar (18 GiB).
O roteamento do nó de trânsito é um pouco mais lento, embora exija apenas cerca de 2 GiB de memória e possui um tempo de pré-processamento mais rápido.
As hierarquias de contração oferecem uma boa troca entre tempos rápidos de pré-processamento, requisitos de pouco espaço (0,4 GiB) e tempos rápidos de consulta.
Nenhum algoritmo é completamente dominado ...
Esta palestra sobre tecnologia do Google de Peter Sanders pode ser interessante
https://www.youtube.com/watch?v=-0ErpE8tQbw
Também esta palestra de Andrew Goldberg
https://www.youtube.com/watch?v=WPrkc78XLhw
Uma implementação de código aberto de hierarquias de contração está disponível no site do grupo de pesquisa Peter Sanders no KIT. http://algo2.iti.kit.edu/english/routeplanning.php
Também uma postagem de blog de fácil acesso, escrita pela Microsoft, sobre o uso do algoritmo CRP ... http://blogs.bing.com/maps/2012/01/05/bing-maps-new-routing-engine/
fonte
Estou um pouco surpreso por não ver o algoritmo de Floyd Warshall mencionado aqui. Esse trabalho de algoritmo é muito parecido com o de Dijkstra. Ele também possui um recurso muito interessante: permite calcular o tempo que desejar continuar permitindo mais vértices intermediários. Por isso, encontrará naturalmente as rotas que utilizam interestaduais ou rodovias rapidamente.
fonte
Eu já fiz isso várias vezes, na verdade, tentando vários métodos diferentes. Dependendo do tamanho (geográfico) do mapa, você pode considerar o uso da função haversine como uma heurística.
A melhor solução que eu fiz foi usar A * com uma distância em linha reta como uma função heurística. Mas então você precisa de algum tipo de coordenada para cada ponto (interseção ou vértice) no mapa. Você também pode tentar diferentes ponderações para a função heurística, ou seja,
onde k é alguma constante maior que 0.
fonte
Provavelmente semelhante à resposta em rotas pré-calculadas entre locais principais e mapas em camadas, mas meu entendimento é que, em jogos, para acelerar o A *, você tem um mapa muito grosseiro para a navegação em macro e um mapa detalhado para navegação até o limite das direções da macro. Portanto, você tem dois pequenos caminhos para calcular e, portanto, seu espaço de pesquisa é muito menor do que simplesmente fazer um único caminho para o destino. E se você estiver fazendo muito isso, terá muitos dados pré-calculados, pelo menos parte da pesquisa é uma pesquisa de dados pré-calculados, em vez de uma pesquisa de um caminho.
fonte
Isso é pura especulação da minha parte, mas suponho que eles possam usar uma estrutura de dados de mapas de influência sobrepondo o mapa direcionado para restringir o domínio de pesquisa. Isso permitiria que o algoritmo de busca direcionasse o caminho para as principais rotas quando a viagem desejada fosse longa.
Como esse é um aplicativo do Google, também é razoável supor que grande parte da mágica seja feita por meio de cache extenso. :) Não ficaria surpreso se o armazenamento em cache dos 5% principais pedidos de rotas do Google Map permitisse que uma grande parte (20%? 50%?) Dos pedidos fosse respondida com uma simples pesquisa.
fonte
Eu pensei mais um pouco sobre isso:
1) Lembre-se de que os mapas representam uma organização física. Armazene a latitude / longitude de cada interseção. Você não precisa verificar muito além dos pontos que estão na direção do seu alvo. Somente se você estiver bloqueado, precisará ir além disso. Se você armazenar uma sobreposição de conexões superiores, poderá limitá-la ainda mais - normalmente você nunca encontrará uma delas de uma maneira que se afaste do seu destino final.
2) Divida o mundo em várias zonas definidas por conectividade limitada, defina todos os pontos de conectividade entre as zonas. Encontre em quais zonas sua origem e destino estão, para a rota da zona inicial e final da sua localização até cada ponto de conexão, para as zonas entre simplesmente mapear entre os pontos de conexão. (Suspeito que muitos destes já estejam pré-calculados.)
Observe que as zonas podem ser menores que uma área metropolitana. Qualquer cidade com características do terreno que a dividam (digamos, um rio) seria de várias zonas.
fonte
Fiquei muito curioso sobre as heurísticas usadas, quando, há algum tempo, recebemos rotas do mesmo local de partida perto de Santa Rosa, para dois acampamentos diferentes no Parque Nacional de Yosemite. Esses destinos diferentes produziram rotas bastante diferentes (via I-580 ou CA-12), apesar do fato de ambas as rotas convergirem pelas últimas 100 milhas (ao longo da CA-120) antes de divergirem novamente por algumas milhas no final. Isso foi bastante repetitivo. As duas rotas estavam separadas por até 80 quilômetros por cerca de 160 quilômetros, mas as distâncias / tempos eram muito próximos um do outro, como seria de esperar.
Infelizmente, não posso reproduzir isso - os algoritmos devem ter mudado. Mas isso me deixou curioso sobre o algoritmo. Tudo o que posso especular é que houve alguma poda direcional que, por acaso, era primorosamente sensível à pequena diferença angular entre os destinos vistos de longe, ou que havia segmentos pré-computados diferentes selecionados pela escolha do destino final.
fonte
Falando em GraphHopper , um rápido planejador de rotas de código aberto baseado no OpenStreetMap, li um pouco da literatura e implementei alguns métodos. A solução mais simples é um Dijkstra e uma melhoria simples é um Dijkstra bidirecional que explora aproximadamente apenas a metade dos nós. Com o Dijkstra bidirecional, uma rota por toda a Alemanha já leva 1 segundo (para o modo de carro), em C seria provavelmente apenas 0,5s ou mais;)
Criei um gif animado de uma pesquisa de caminho real com o Dijkstra bidirecional aqui . Além disso, existem mais algumas idéias para tornar o Dijkstra mais rápido, como fazer A *, que é um "Dijkstra orientado a objetivos". Também criei uma animação gif para ele.
Mas como fazê-lo (muito) mais rápido?
O problema é que, para uma pesquisa de caminho, todos os nós entre os locais precisam ser explorados e isso é realmente caro, já que na Alemanha existem vários milhões deles. Mas um ponto de dor adicional de Dijkstra etc é que essas pesquisas usam muita RAM.
Existem soluções heurísticas, mas também soluções exatas que organizam o gráfico (rede rodoviária) em camadas hierárquicas, ambas têm vantagens e desvantagens e resolvem principalmente o problema de velocidade e RAM. Eu listei alguns deles nesta resposta .
Para o GraphHopper, decidi usar as hierarquias de contração porque é relativamente "fácil" de implementar e não leva anos para a preparação do gráfico. Ainda resulta em tempos de resposta muito rápidos, como você pode testar em nossa instância online GraphHopper Maps . Por exemplo, da África do Sul ao leste da China, o que resulta em uma distância de 23000 km e em quase 14 dias de tempo de carro e levou apenas 0,1s no servidor.
fonte
Eu trabalhei no roteamento por alguns anos, com uma recente explosão de atividade motivada pelas necessidades de meus clientes e descobri que o A * é facilmente rápido o suficiente; não há realmente necessidade de otimizações ou algoritmos mais complexos. Rotear sobre um gráfico enorme não é um problema.
Mas a velocidade depende de ter toda a rede de roteamento, com o que quero dizer o gráfico direcionado de arcos e nós representando segmentos e junções de rota, respectivamente, na memória. O tempo principal principal é o tempo gasto para criar esta rede. Alguns números aproximados baseados em um laptop comum executando o Windows e roteando por toda a Espanha: tempo necessário para criar a rede: 10 a 15 segundos; tempo necessário para calcular uma rota: muito curto para medir.
A outra coisa importante é poder reutilizar a rede para os cálculos de roteamento que você desejar. Se o seu algoritmo marcou os nós de alguma forma para registrar a melhor rota (custo total para o nó atual e o melhor arco para ele) - como em A * -, você deve redefinir ou limpar essas informações antigas. Em vez de passar por centenas de milhares de nós, é mais fácil usar um sistema de números de geração. Marque cada nó com o número de geração de seus dados; aumente o número de geração ao calcular uma nova rota; qualquer nó com um número de geração mais antiga é obsoleto e suas informações podem ser ignoradas.
fonte
Vejo o que há com os mapas no OP:
Observe a rota com o ponto intermediário especificado: a rota segue ligeiramente para trás devido a essa estrada que não é reta.
Se o algoritmo deles não voltar atrás, ele não verá a rota mais curta.
fonte
Um algoritmo de caminho mais curto para todos os pares calculará os caminhos mais curtos entre todos os vértices em um gráfico. Isso permitirá que os caminhos sejam pré-calculados em vez de exigir que um caminho seja calculado toda vez que alguém desejar encontrar o caminho mais curto entre uma origem e um destino. O algoritmo de Floyd-Warshall é um algoritmo de caminho mais curto para todos os pares.
fonte
Os mapas nunca levam em consideração o mapa inteiro. Meu palpite é: - 1. De acordo com a sua localização, eles carregam um local e os pontos de referência nesse local. 2. Quando você pesquisa o destino, é quando eles carregam a outra parte do mapa e criam um gráfico em dois lugares e, em seguida, aplicam os algoritmos de caminho mais curto.
Além disso, existe uma técnica importante Programação dinâmica que, suspeito, é usada no cálculo dos caminhos mais curtos. Você pode se referir a isso também.
fonte