スキップしてメイン コンテンツに移動

ダイクストラ法

Introduction

今日は、ダイクストラ法について書きます。ダイクストラ法とは最短距離を求めるアルゴリズムです。地図はグラフで表されます。もし、まだ this pageを見ていない方は先にこちらをご覧ください。今回はこの記事を前提としています。このページでは、グラフの定義と、ヒープ構造について書いています。ダイクストラ法ではヒープ構造を使って、かなりの計算量を落とします。
このスライドはダイクストラ法を説明したスライドです。

Overview

  • アルゴリズム
  • 実装

アルゴリズム

このアルゴリズムは
  1. スタート始点のノードを決める。そして、それをAと名付ける。
  2. 各ノードに$d=\infty$を割り当てる。ただし、スタート地点はd=0
  3. Aの隣接ノードのリストをadj_listと名付ける。
  4.  For adj in adj_list:  If d of adj > d of A + weight to adj -> d = A + weight to adj.
  5. グラフnetworkからAを取り除く
  6. グラフnetworkの中で最初のdを持っているノードをAとし、4に戻る。
となっています。
このアルゴリズムを図を用いて説明します。

 このグラフを使って説明します。
 初めに、スタート地点を決めます。そして、各ノードに$d=\infty$を割り当てます。

 Aから始まります。Aの隣接ノードであるBのdを更新します。もし、現在のBよりもAのdとA->Bへの重みを足したもののほうが小さいならdをその値に更新します。同じようにCnのdを更新します。

次にAを取り除きます。
 次はBから始まります。Aと同じことをやります。


このダイクストラ法では今のような操作をグラフの全てのノードに×がつくまで続きます。


実装

このアルゴリズムでは$O(log(|V|^2))$という計算量を持っています。最小のdを持つノードを探すのに時間がかかります。
しかし、ヒープ構造を使えばO((E+V)log(V))に減らせます。ヒープ構造で現時点でのノードのdをヒープ構造で保存しておけば、ヒープ構造から取り出せば、最小のdを持つノードを簡単に取り出せます。


ダイクストラ法はPython 3で実装しました。
コードはgithubに乗せています。

100個のノードを作り、各ノードに0~30の間からランダムな数を選択しedgeを作ります。



結果は



このgifは各ノードの最短距離の更新を表したものです。



コメント

このブログの人気の投稿

カーネルK-means 理論編

Introduction English ver 今日は、カーネルK-meansの理論について書きます。カーネルK-meansは通常のK-meansの欠点を補うことができます。通常のK-meansの欠点とカーネルK-meansの強みも説明します。もし、まだ御覧になられていなければ、通常の K-means 理論編 の記事を見ていただけるとよいのではないかと思います。 カーネルK-meansの実装編 も併せてご覧ください。 概要 K-meansの弱点 カーネルトリック カーネルK-means アルゴリズム K-meansの弱点 例えば、次のようなデータを用意します。 このデータはK-meansによってうまく分類することはできません。なぜなら通常のK-meansでは、データとプロトタイプのユークリッド距離に依存しているからです。そのため、このような円状に分布しているデータはうまく分類することができません。 プロトタイプとはそれぞれのクラスにあり、そのクラスを代表するようなもののことです。K-meansでは各クラスの平均ベクトルとなります。それゆえ、以下のような分類になってしまいます。 このようなデータではK-meansはうまくいきません。 K-meansで分類できるデータセットは次のように各クラスで固まっている必要があります。 カーネルK-meansはK-meansの弱点を補います。 カーネルトリック 初めに、カーネルトリックを説明します。 線形分離できないようなデータ$X$を例えば次のように線形分離できるように$\phi(x)$に送る写像$\phi$を考えます。 カーネルは次のように定義されます。 $$K(x,y) = \phi(x)^T \phi(y)$$ $\phi$を具体的に計算することは難しいですが、$K(x,y)$を計算することなら簡単です。 この手法をカーネルトリックと呼ばれます。 カーネルK means K-meansの目的関数を復習しておきます。 $$J = \sum_{n=1}^{N} \sum_{k=1}^{K} r_{nk} ||x_n-\mu_k||^2$$ ここで、 プロトタイプは$\mu_i ~\forall k \in K$としま...

Pythonでスペースを扱う

English ver Introduction 失敗 成功 Reference Introduction コマンドラインで次のような表示をさせたい。 apple   apple     apple       apple         apple 失敗 次のようなprintを使ったcodeでは失敗する def main () : i = 0 while i< 5 : print( 'apple' ) j = 0 while j < i: print( ' ' ) j = j + 1 i = i + 1 if __name__ == '__main__' : main() 結果は、、、 Printは使うごとに改行してしまうのです。 成功 次のようなcodeを見てください。 import sys def main () : i = 0 while i < 5 : print( 'apple' ) j = 0 while j <= i: sys.stdout.write( ' ' ) j = j + 1 i = i + 1 if __name__ == '__main__' : main() sys.stdout.write は改行を無視してくれます。 結果!! 一つ注意することはsys.stdout.weiteはstrしか受け付けないことです。 Reference https://www.lifewithpython.com/2013/12/python-print-without-.html