← トップページブラウザー内で実験
RASCAL / INTERACTIVE LAB

カーナビ経路探索実験室

架空の街の道路網で、カーナビがルートを決める仕組みを観察。ダイクストラ法・A*・双方向探索を動かし、渋滞や通行止めでルートが変わる様子を確かめよう。

入力や実験結果は送信・保存しません。ページへの通常のアクセス記録は残ります。

1. 街の地図と道路状況

交差点が約500m間隔で並ぶ架空の街です。地図をクリックして、出発地・目的地の移動や、渋滞・通行止めの設置ができます(もう一度クリックで解除)。

一般道 30km/h幹線道路 50km/h高速道路 80km/h渋滞(通過時間3倍)通行止め確定した交差点目的地側から確定(双方向)選ばれた経路

2. ルートを探索する

0確定した交差点
0これから調べる候補
—経路の距離
—所要時間(渋滞込み)
—最適ルートとの差

ルート案内

    表示のため、1フレームに数か所ずつ実際に探索を進めています。アニメーションの時間は計算速度ではありません。所要時間は上記の架空の速度から計算した値です。

    3. 4つの探し方を一括比較

    いまの地図・出発地・目的地・条件で、4方式をすべて最後まで計算します。「確定した交差点」が少ないほど、少ない手間でルートを決められたことを意味します。

    探し方確定した交差点距離所要時間最適との差最短の保証

    カーナビは地図を「グラフ」として持っている

    カーナビの地図データでは、交差点が点(ノード)、交差点どうしを結ぶ道路が線(リンク)です。それぞれの線には「長さ」「制限速度や平均速度」「一方通行」「右折できるか」などの情報が付いています。

    ルート探索とは、線ごとにコスト(距離優先なら長さ、時間優先なら通過にかかる秒数)を決め、出発地から目的地までのコストの合計が最小になる線のつなぎ方を探す問題です。条件を変えるとコストの付け方が変わるので、同じ地図でも別のルートが選ばれます。

    ダイクストラ法

    出発地から「コストの合計が小さい順」に交差点を1つずつ確定していきます。確定した交差点から伸びる道を見て、隣の交差点までのコストが今の記録より小さければ書き換えます。目的地が確定した瞬間に、それが最小コストのルートです。

    地図上では、出発地を中心に水たまりが広がるように確定が進みます。目的地と反対方向も同じように調べるので、手間は多めです。

    A*(エースター)

    「ここまでのコスト+目的地までの見積もり」が小さい順に確定します。このページの見積もりは、時間優先なら「目的地までの直線距離 ÷ 最高速度80km/h」です。

    見積もりが実際のコストを上回らない限り、最短のルートが保証されます。目的地の方向に細長く探索が伸び、確定する交差点が減ります。

    双方向ダイクストラ

    出発地(青)と目的地(ピンク)の両側から同時に探し、2つの探索が出会ったところでつなぎます。両側の「まだ確定していない最小のコスト」の合計が、見つけたルートのコスト以上になった時点で、それより良いルートはないと判断して終了します。

    半径rの円2つは、半径2rの円1つより面積が小さいため、探索範囲が狭くなります。

    簡易階層探索(近似)

    出発地と目的地の近く(黄色い円)以外では一般道を使わず、幹線道路と高速道路だけで探します。人が地図を見るときの「近くの大通りに出て、高速に乗る」という考え方に近い方法です。

    調べる交差点はさらに減りますが、裏道の近道を見落とすことがあり、最短の保証はありません。表の「最適との差」で確かめてみましょう。

    実際のカーナビがしている工夫

    日本全国の道路地図には、交差点が数千万か所あります。そのままダイクストラ法をかけると時間もメモリも足りないため、一般に知られている手法として次のような工夫が組み合わされます。メーカーごとの細かな実装は公開されていない部分も多く、ここで紹介するのは代表的な考え方です。

    このデモでの単純化

    速度は一般道30km/h・幹線道路50km/h・高速道路80km/hで一定、渋滞は通過時間を3倍にするだけです。一方通行、右左折のコスト、信号待ち、料金、時間帯による変化は含みません。街は乱数から作った架空の地図で、実在の地図データは使っていません。

    ダイクストラ法の手順(擬似コード)
    コスト[出発地] = 0、それ以外 = ∞
    候補リスト = {出発地}
    候補リストが空でない間:
      u = 候補リストでコスト最小の交差点を取り出す
      u が確定済みなら次へ
      u を確定する
      u が目的地なら終了(記録をたどればルートになる)
      u から伸びる道 (u→v, 道のコスト c) それぞれについて:
        コスト[u] + c < コスト[v] なら
          コスト[v] = コスト[u] + c、ひとつ前[v] = u
          v を候補リストに入れる
    
    A* は「取り出す順番」を コスト[v] + 見積もり(v→目的地) に変えるだけ。