クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

最短の道を探す:グラフと幅優先探索

このレッスンのあとで: 幅優先探索を使って、グラフの上で最短の道の長さを求められる。

50分のレッスンコマンド1件JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

乗り換えの少ない行き方

地図アプリで駅Aから駅Fへ行く道を調べると、乗り換えの少ない行き方が出ます。道は何通りもあるのに、アプリはどう選んでいるのでしょう。

駅と線路を「点と線」で表したものが、グラフです。グラフの上で最短の道を探す手順があります。

このレッスンのゴール

メモ

幅優先探索を使って、グラフの上で最短の道の長さを求められる。

重要な言葉

ことばいみ
グラフ点と、点どうしをつなぐ線でできた図
ノードグラフの点で、駅や人にあたるもの
エッジノードどうしをつなぐ線
隣接エッジで直接つながっていること
幅優先探索近いノードから順に、輪を広げて調べる探し方

学生が入力するセルは、このプレビューでは空白です。

グラフはノードとエッジでできている

駅がノード、駅と駅をつなぐ線路がエッジです。エッジでつながった二つのノードは、隣接していると言います。

Python では、ノードごとに、隣のノードのリストを持つ辞書で表せます。これを隣接リストと呼びます。

グラフを辞書で表す

コード: python
# 駅ごとに、隣の駅のリストを持つ
graph = {
    "A": ["B", "C"],
    "B": ["A", "D"],
    "C": ["A", "D", "E"],
    "D": ["B", "C", "F"],
    "E": ["C", "F"],
    "F": ["D", "E"],
}

print(graph["C"])
# "C" を "F" に変えて、隣の駅を確かめましょう

幅優先探索は輪を広げて調べる

池に石を投げると、波が輪になって広がります。幅優先探索も、出発点に近いノードから、輪を広げるように調べます。

調べる順番はキューで決めます。ノードを取り出し、まだ見ていない隣のノードを、キューの後ろに入れます。

例:Aから始める探索

取り出す駅新しく入れる駅キューの中身
AB, CB, C
BDC, D
CED, E
DFE, F
EなしF
Fなし空

学生が入力するセルは、このプレビューでは空白です。

幅優先探索の訪問順を出す

コマンド
docker exec jupyter python3 -c 'exec("graph = {\"A\": [\"B\", \"C\"], \"B\": [\"A\", \"D\"], \"C\": [\"A\", \"D\", \"E\"], \"D\": [\"B\", \"C\", \"F\"], \"E\": [\"C\", \"F\"], \"F\": [\"D\", \"E\"]}\nqueue = [\"A\"]\nseen = [\"A\"]\norder = []\nwhile len(queue) > 0:\n    here = queue.pop(0)\n    order.append(here)\n    for next_stop in graph[here]:\n        if next_stop not in seen:\n            seen.append(next_stop)\n            queue.append(next_stop)\nprint(\" \".join(order))")'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

見た駅を覚えておく理由

実行の結果は A B C D E F です。表と同じ順番で駅を調べています。

見た駅を seen に覚えておくのが大事です。覚えないと、AからBへ行って、またAへ戻るように、同じ駅を何度も回ってしまいます。

最短の道は、何本のエッジか

A から見ると、B と C は1本、D と E は2本、F は3本のエッジを通った先です。輪が広がるたびに、本数が1ずつ増えます。

幅優先探索は近い順に調べるので、初めて着いたときの本数が、最短です。乗り換えが少ない道が、これにあたります。

例:Aからの最短の本数

駅Aから何本か通る道の例
A0A
B1A, B
D2A, B, D
F3A, B, D, F

学生が入力するセルは、このプレビューでは空白です。

よくある間違い

注意

近いと思った駅から、一本の道をどこまでも進めばよいと考えがちです。それでは最短とは限りません。近いノードを順に全部調べるから、最初に着いたときの本数が最短だと言えます。

このラボとソースについて: JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。