地図プロバイダー(GoogleやYahoo! Mapsなど)はどのように道案内を提案しますか?
確かに、実際のデータは何らかの形で存在し、確かに距離だけでなく、走行速度、歩道の存在、列車のスケジュールなども含まれています。ただし、データがもっと単純な形式であるとします。エッジウェイトが距離を反映している。ある点から別の点への方向を素早く計算できるようにしたい。時にはこれらのポイントは(1つの都市内で)互いに接近していることがありますが、離れていることがあります(クロスカントリー)。
グラフが膨大であるため、ダイクストラのアルゴリズムのようなグラフアルゴリズムは機能しません。幸いなことに、A *のようなヒューリスティックなアルゴリズムはおそらくうまくいくでしょう。しかし、私たちのデータは非常に構造化されており、おそらく何らかの階層的なアプローチでうまくいくかもしれません。 (たとえば、遠く離れた特定の「キー」ポイント間の事前計算された方向と、いくつかのローカル方向を格納します。その場合、2つの遠いポイントの方向はキーポイントへのローカル方向、別のキーポイントへのグローバル方向、そしてローカル方向再び指示します。)
実際にはどのようなアルゴリズムが使用されていますか?
PS。この質問は、オンライン地図作成の方向性に関する疑問を見つけることによって動機付けられました。三角形の不等式とは反対に、Googleマップでは X-Z のように中間点を使用するよりも X-Z の方が時間がかかり、遠いと考えられることがあります。しかし、彼らの歩く方向もまた別のパラメータを最適化するのでしょうか。
PPSこれは、三角形の不等式に対する別の違反です。これらは、ある種の段階的アプローチを使用することを(私には)示唆しています。 X-Z vs. X-Y-Z 。前者は、ちょっと邪魔にならなくても有名なBoulevard de Sebastopolを使用しているようです。
編集:これらの例はどちらも動作しなくなったようですが、どちらも最初の投稿時には動作していました。
ルーティングアルゴリズムの作業を含む、マッピング会社での作業に18か月を費やした人と言えば、そうです--- Dijkstra's は、いくつかの修正を加えて作業します。
これらの線に沿って変更を加えると、非常に妥当な時間枠でクロスカントリールーティングさえも行うことができます。
この質問は、ここ数年で活発な研究分野となっています。主な考え方は、グラフ上で前処理once、スピードアップ all 次のクエリを実行することです。この追加情報により、旅程は非常に速く計算することができます。それでも、Dijkstraのアルゴリズムはすべての最適化の基礎です。
Arachnidは、階層情報に基づく双方向検索とEdge pruningの使用法について説明しました。これらの高速化手法は非常にうまく機能しますが、最新のアルゴリズムはこれらの手法よりも常に優れています。現在のアルゴリズムでは、大陸道路網では1ミリ秒よりもかなり短い時間で最短経路を計算できます。 Dijkstraの修正されていないアルゴリズムを高速に実装するには、10秒が必要です。
記事 Engineering Fast Route Planning Algorithms はその分野の研究の進歩の概観を与えます。詳細については、その論文の参考文献を参照してください。
最も速い既知のアルゴリズムは、データ内の道路の階層的状態に関する情報、すなわちそれが高速道路であるか地方道路であるかについての情報を使用しない。代わりに、前処理ステップでルート計画をスピードアップするために最適化された独自の階層を計算します。その後、この事前計算を使用して検索を絞り込むことができます。出発地点や目的地の遅い道路から遠く離れている場合は、ダイクストラのアルゴリズムで考慮する必要はありません。利点はとても良いパフォーマンスと正確さ結果の保証です。
最初の最適化されたルートプランニングアルゴリズムは、静的道路ネットワークのみを対象としていました。つまり、グラフ内のエッジには固定コスト値があります。これは実際には当てはまりません。なぜなら、私たちは渋滞や車両に依存する規制などの動的な情報を考慮に入れたいからです。最新のアルゴリズムでもこのような問題に対処できますが、解決すべき問題がまだあり、研究が進められています。
TSPの解を計算するために最短経路距離が必要な場合は、おそらく出発地と目的地の間のすべての距離を含む行列に興味があるでしょう。そのためには、 ハイウェイ階層を使用した多対多の最短経路の計算 を考慮することができます。これは過去2年間の新しいアプローチによって改善されていることに注意してください。
三角不等式の違反に対処するだけで、うまくいけば、それらが最適化している余分な要因は常識です。 混沌and破壊 になる可能性があるため、必ずしも最短または最速の経路を使用する必要はありません。あなたがあなたの指示がトラックにやさしくて、そしてすべてのsat-nav-followドライバーを彼らに送ってもらうことに対処することができる主要なルートを好みたいならば、あなたはすぐに三角形の不等式を捨てます[1]。
YがXとZの間の狭い住宅街である場合、ユーザーがX-Y-Zを明示的に要求した場合は、おそらくYを介したショートカットのみを使用したいと思うでしょう。彼らがX-Zを要求するならば、たとえそれがもう少し長くて、そしてもう少し長くかかるとしても、彼らは主要道路に固執するべきです。それは Braessのパラドックス - に似ています - 誰もが最短で最速のルートを選択しようとすると、結果として生じる混雑は、それがもう誰にとっても最速のルートではないことを意味します。ここから私達はグラフ理論からゲーム理論に迷いました。
[1]実際、一方通行の道路を許可して対称性の要件を失うと、生成された距離が数学的な意味での距離関数になるという希望はすべてなくなります。三角形の不等式も失うことは、傷の中の塩をこするだけです。
これが、比較して正しいことが証明されている世界最速のルーティングアルゴリズムです。
http://algo2.iti.uka.de/schultes/hwy/schultes_diss.pdf
これについては、Googleの技術的な話です。
http://www.youtube.com/watch?v=-0ErpE8tQbw
これがschultesによって議論されたhighway-hierarchyiesアルゴリズムの実装です(現在ベルリンでのみ、私はインターフェースを書いています、そしてモバイル版も開発中です):
私はこれまでグーグル、マイクロソフト、ヤフーマップなどを扱ったことがないので、どのように機能するのかわかりません。
しかし、私はエネルギー会社向けのカスタムサプライチェーン最適化システムを設計しました。これには、トラックのトラック用のスケジューリングおよびルーティングアプリケーションが含まれていました。しかし、私たちのルーティング基準は、建設や交通の渋滞、車線の閉鎖よりもはるかにビジネス固有のものでした。
私たちはトラックをスケジュールし、ルーティングするためにACO(アントコロニー最適化)と呼ばれる技術を採用しました。この技法は、ルーティング問題を解決するために巡回セールスマン問題に適用されたAI技法です。 ACOのトリックは、グラフ解決モデルがいつ終了するか(エラーが十分小さい時)を認識できるように、ルーティングの既知の事実に基づいてエラー計算を構築することです。
あなたはこのテクニックについてもっと知るためにグーグルACOかTSPをすることができます。私はこのためにオープンソースのAIツールを使ったことはありません。
静的道路網の問い合わせ時間に関する現在の最新技術は、Abrahamらによって提案されたハブラベリングアルゴリズムである。 http://link.springer.com/chapter/10.1007/978-3-642-20662-7_2 。徹底的にそしてよく書かれた分野の調査は最近マイクロソフトのテクニカルレポートとして発表されました http://research.Microsoft.com/pubs/207102/MSR-TR-2014-4.pdf 。
ショートバージョンは...
ハブラベリングアルゴリズムは、静的道路ネットワークに対して最速のクエリを提供しますが、実行には大量のRAMを必要とします(18 GiB)。
トランジットノードルーティングはわずかに遅くなりますが、それはおよそ2 GiBのメモリしか必要とせず、より速い前処理時間を持ちます。
縮小階層は、素早い前処理時間、低いスペース所要量(0.4 GiB)、および速い照会時間の間で、良いトレードオフを提供します。
完全に支配的なアルゴリズムはありません...
Peter Sandersによるこのグーグルのテクニカルトークは興味深いかもしれません
https://www.youtube.com/watch?v=-0ErpE8tQbw
Andrew Goldbergによるこの講演も
https://www.youtube.com/watch?v=WPrkc78XLhw
契約階層のオープンソース実装は、KITのPeter Sanders研究グループのWebサイトから入手できます。 http://algo2.iti.kit.edu/english/routeplanning.php
また、CRPアルゴリズムの使用法がそこにMicrosoftによって書かれた簡単にアクセスできるブログ記事... http://blogs.bing.com/maps/2012/01/05/bing-maps-new-routing-engine /
グラフが膨大であるため、ダイクストラのアルゴリズムのようなグラフアルゴリズムは機能しません。
Dijkstraは通常完全なグラフを見るのではなく、非常に小さい部分集合(グラフの相互接続性が高いほど、この部分集合は小さい)を見るので、この議論は必ずしも成り立たない。
ダイクストラは、行儀の良いグラフに対して実際にはかなりうまく機能するかもしれません。一方、慎重なパラメータ化では、A *は常に同じように、あるいはそれ以上のパフォーマンスを示します。あなたはそれがあなたのデータに対してどのように実行されるかをすでに試しましたか?
そうは言っても、私は他の人々の経験について聞くことも非常に興味があると思います。もちろん、Google Mapの検索のような有名な例は特に興味深いものです。私は有向最近傍ヒューリスティックのような何かを想像することができました。
Floyd Warshallのアルゴリズム ここで言及されていないのを見て私は少し驚いています。このアルゴリズムはDijkstraのアルゴリズムとよく似ています。それはまた、あなたがより多くの中間頂点を許可し続けたい限りそれがあなたが計算することを可能にするという1つの非常に素晴らしい機能も持っています。それで、それは当然速やかに州間高速道路を使うルートを見つけるでしょう。
私はこれを何度もやりました、実際には、いくつかの異なる方法を試してみました。地図のサイズ(地理的)によっては、haversine関数をヒューリスティックとして使用することを検討することをお勧めします。
私が行った最善の解決策は、ヒューリスティック関数として直線距離を持つA *を使用することでした。しかしその場合は、地図上の各点(交差点または頂点)に何らかの座標が必要です。ヒューリスティック関数に対して異なる重み付けを試すこともできます。
f(n) = k*h(n) + g(n)
ここで、kは0より大きい定数です。
おそらく、主要な場所と階層化された地図との間の事前に計算されたルートに対する回答に似ていますが、ゲームでは、A *を高速化するために、マクロ方向の境界へのナビゲーション。したがって、計算するパスは2つあります。したがって、検索スペースは、目的地へのパスを1つ作成するよりもはるかに小さくなります。そして、これを大量に行うビジネスをしているのであれば、そのデータの多くは事前に計算されているので、検索の少なくとも一部はパスの検索ではなく事前計算されたデータの検索です。
GraphHopper と言えば、OpenStreetMapをベースにした高速オープンソースルートプランナーです。私は少し文献を読み、いくつかの方法を実装しました。最も簡単な解決策はダイクストラであり、単純な改良は双方向のダイクストラで、ほぼ半分のノードしか探索しません。双方向Dijkstraでは、ドイツ全土を通るルートはすでに1秒かかります(自動車モードの場合)。Cでは、たぶん0.5秒かそこらでしょう;)
双方向Dijkstraを使った実際のパス検索のアニメーションGIFを作成しました ここ 。また、(目標指向のDijkstraである)A *をするような Dijkstraをより速くする するために、さらにいくつかのアイデアがあります。また、私は gif-animation を作成しました。
しかしそれを(もっと)早くするにはどうすればいいですか?
問題は、パス検索ではロケーション間のすべてのノードを探索する必要があることです。これは、すでにドイツにあるように数百万もあるため、実際にはコストがかかります。しかし、Dijkstraなどのもう1つの難点は、このような検索では大量のRAMが使用されることです。
ヒューリスティックな解決策もありますが、グラフ(道路網)を階層的に階層化する厳密な解決策もあります。どちらも長所と短所があり、主に速度とRAMを解決します。それらのいくつかを この答え にリストしました。
GraphHopperでは Contract Hierarchies を使うことにしました。それは比較的実装が簡単で、グラフの作成に時間がかからないからです。それでも、私たちのオンラインインスタンスでテストできるような非常に速い応答時間をもたらします GraphHopper Maps 。例えば。 南アフリカから中国東部へ その結果、23000kmの距離と約14日間の車の運転時間が得られ、サーバーではわずか0.1秒かかりました。
これは私の側では純粋な憶測ですが、検索ドメインを絞り込むために有向マップをオーバーレイするインフルエンスマップデータ構造を使用する可能性があります。これにより、目的の旅行が長い場合、検索アルゴリズムはパスを主要ルートに向けることができます。
これがGoogleのアプリであることを考えると、多くの魔法は大規模なキャッシュを介して行われると考えるのも妥当です。 :)最も一般的な5%のGoogle Mapルートリクエストをキャッシュすることで、簡単な検索で大きなチャンク(20%〜50%)のリクエストに回答できる場合でも、私は驚かないでしょう。
私が使用したヒューリスティックについて非常に興味がありました、しばらく前に私達がサンタローザ近くの同じ出発地点からヨセミテ国立公園の2つの異なるキャンプ場までのルートを得たとき。両方のルートが最後の数マイルで再び分岐する前に最後の100マイル(CA-120に沿って)に収束したという事実にもかかわらず、これらの異なる目的地はまったく異なるルートを(I-580またはCA-12経由で)生成しました。これはかなり再現性がありました。 2つのルートは約100マイルの間最大50マイル離れていましたが、あなたが期待するように距離/時間はお互いにかなり近かった。
ああ私はそれを再現することはできません - アルゴリズムが変更されている必要があります。しかし、それは私がアルゴリズムについて興味を持っていました。私が推測できるのは、遠くから見たときに目的地間の小さな角度の違いに非常に敏感に反応するような偶然の剪定があるか、あるいは最終目的地の選択によって異なる事前計算セグメントが選択されたということです。
私はこれについてもう少し考えを持っていました:
1)地図は物理的な組織を表していることを忘れないでください。すべての交差点の緯度/経度を保存します。あなたはあなたの目標の方向にある点をはるかに超えてチェックする必要はありません。あなた自身がブロックされていると感じた場合にのみ、あなたはこれを超える必要があります。あなたが優れた接続のオーバーレイを保存するなら、あなたはそれをさらに制限することができます - あなたは通常あなたの最終目的地から遠ざかるような方法でそれらの1つに遭遇することは決してないでしょう。
2)限られた接続性によって定義されたゾーンの全体の束に世界を分割し、ゾーン間のすべての接続ポイントを定義します。自分の場所から各接続ポイントまでの開始ゾーンと終了ゾーンのルート、接続ポイント間の単純なマップのゾーンについて、ソースとターゲットがどのゾーンにあるかを調べます。 (私は後者の多くがすでに事前に計算されていると思います。)
ゾーンは大都市圏よりも小さい場合があります。それを分割する地形の特徴を持つ都市(たとえば、川)は複数のゾーンになります。
私はクライアントのニーズによって促進された最近の活動のバーストで数年間ルーティングに取り組んできました、そして私はA *が十分に速いのが簡単であるとわかりました。最適化やもっと複雑なアルゴリズムを探す必要はまったくありません。膨大なグラフ上でのルーティングは問題になりません。
しかし、速度はルーティングネットワーク全体を持つことにかかっています。これは、ルートセグメントとジャンクションをそれぞれ表す円弧とノードの有向グラフをメモリに格納することを意味します。主な時間のオーバーヘッドは、このネットワークを作成するのにかかる時間です。いくつかのおおまかな数字は、Windowsを実行しているスペインの全域にわたるルーティングを基にしています。ネットワークを作成するのにかかる時間:10-15秒。ルートの計算にかかる時間:測定するには短すぎる。
もう一つの重要なことはあなたが好きなだけルーティング計算のためにネットワークを再利用できることです。 A *の場合と同様に、アルゴリズムが何らかの方法でノードにマークを付けて(現在のノードまでの合計コスト、およびそれに最適な円弧)最適な経路を記録した場合、この古い情報をリセットまたは消去する必要があります。何十万ものノードを経由するのではなく、世代番号システムを使用する方が簡単です。各ノードにそのデータの世代番号を付けます。新しいルートを計算するときに世代番号を増やします。古い世代番号を持つノードは古く、その情報は無視できます。
OPのマップに何が起きているのかわかります。
中間地点を指定してルートを確認します。その道路は直線ではないため、ルートはわずかに後方に進みます。
彼らのアルゴリズムが後戻りしないなら、それはより短いルートを見ないでしょう。
全ペア最短経路アルゴリズムは、グラフ内のすべての頂点間の最短経路を計算します。これは、誰かが発信元と宛先との間の最短経路を見つけたいと思う度に経路が計算されることを要求する代わりに経路が事前計算されることを可能にする。 Floyd-Warshallアルゴリズムは、全対最短経路アルゴリズムです。