okinawa

IT勉強メモ

ダイクストラ法

放送大学の問題解決の数理で学んだアルゴリズムの覚書。

ダイクストラ法とは

2頂点間の最短距離を求める。

重みがマイナスだと使えない。

計算量

O(頂点数2) (オリジナルの場合)

O((頂点数+辺の数)* log頂点数) (優先度付きキューの場合)

※厳密な計算量はWikipediaを参考にすること。

処理概要

  1. 全ての頂点に、始点からの距離無限大を仮で書き込む。(初期化)
  2. 始点に、始点からの距離0を書き込む。(初期化)
  3. 次に行ける頂点に対して、始点からの距離を計算、現在書き込まれている距離より短ければ更新する。
  4. 始点からの距離が最も小さい&未訪問の頂点を選び、その頂点に行く。
  5. 未訪問頂点がまだあれば、3~4を繰り返す。
  6. すべての頂点が訪問済になったら終了。

ソースコード

グラフ

N=6
visited=[False]*N
#始点からの距離。初めは全頂点に無限値にする
startFromDistance=[math.inf]*N 

#(頂点番号,重み)のタプルを持つグラフ
G=[[(1,1),(2,5)]
   ,[(0,1),(2,4),(3,2)]
   ,[(0,5),(1,2),(4,2)]
   ,[(2,3),(5,3)]
   ,[(2,1),(5,4)]
   ,[]]

def dijkstra(G, vertex):
  heap=[(0,0)]#重み、頂点番号(優先度付きキュー。最も重みの軽い頂点から優先で取り出す)
  startFromDistance[0] = 0

  while len(heap) > 0:
    distance, now = heapq.heappop(heap)
    
    if visited[now]:
      continue
    visited[now] = True

    for next, weight in G[now]:
      if visited[next]:
        continue

      # nowから到達可能な頂点の距離更新
      newDistance = startFromDistance[now] + weight
      if newDistance < startFromDistance[next]:
        startFromDistance[next] = newDistance

        #次の行き先候補を格納
        heapq.heappush(heap, (newDistance, next))
  return startFromDistance

print(dijkstra(G, 0)) #[0, 1, 5, 3, 7, 6]

定式化

最短経路問題を定式化する。

頂点集合(V)={0 1 2 3 4 5}

辺集合(Ei,j)={(0,1), (0,2),(1,0),(1,2),(1,3),(2,0),(2,1),(2,4),(3,2),(3,5),(4,2),(4,5)}

重み集合(Wi,j)=W01=1, W02=5, W10=1, W12=2, W13=2, W20=5, W21=4, W24=2, W32=3,W35=3, W42=1, W45=4

決定変数(Xi,j)
「辺(i, j) ∈ E」 が最短路に含まれる場合、Xi,j=1

「辺(i, j) ∈ E 」が最短路に含まれない場合、Xi,j=0

移動距離Zは

始点sの出入

終点tの出入

始点と終点以外の地点の出入り

Xijは0か1をとる  Xij ∈ {1,0} for (i, j) ∈ E

決定変数が0か1をとる問題を整数最適化問題と呼ぶ。

定式化例題

グラフ
画像のグラフを最短経路問題として定式化する。

・目的変数

Z(移動距離)= X01 + 5X02 + X10 + 2X12 + 2X13 + 5X20 + 4X21 + 2X24 + 3X32 + 3X35 + 4X45

・制約条件

(X01 + X02) -(X10+X20) = 1   始点sの出入り

(X42 + X45) - X24 = -1     終点tの出入り

(X10 + X12+X13) - (X01+X21) = 0 頂点1の出入り

(X20+X21+X24) - (X02 + X12 + X32 + X42) = 0 頂点2の出入り

(X32 + X35) - X13 = 0  頂点3の出入り

-(X35 + X45) = 0  頂点5の出入り

XIJ >= 0 for (i, j) ∈ E  Xijは0か1をとる

参考

Dijkstra's Algorithm

ダイクストラ法の解説とPythonでの実装例 - PyDocument

www.youtube.com