dijkstra

Rubyで最短経路を探索しよう! - hp12c
経路探索アルゴリズムの「ダイクストラ法」と「A*」をビジュアライズしてみた - てっく煮ブログ 跡地
ダイクストラ法(最短経路問題)

頭で消化したつもりなので清書。
うーん、径路の遡りが醜い、醜すぎるので後で直す。
これを宣言的に書くにはどうするんだろう?
本当は scheme で書けるようになっておきたい。

def dijkstra(node_data)
  nodes = {}
  node_data.each {|k,v|
    nodes[k] = Node.new(k, v)
  }
  nodes["s"].cost = 0
  
  puts "#### initialize"
  puts nodes.values.join("\n")
  
  focus_node = nodes["s"]
  while focus_node
    focus_node.done = true
    focus_node.link.each_with_index {|key,i|
      newcost = focus_node.cost + focus_node.link_cost[i]
      edge_node = nodes[key]
      if newcost < edge_node.cost
        edge_node.cost = newcost
        edge_node.done = false if edge_node.done
      end
    }

    focus_node = nodes.values.select{|node|
      ! node.done and node.key != focus_node.key
    }.sort{|a, b|
      a.cost<=>b.cost
    }.first
  end

  puts "#### calculated"
  puts nodes.values.join("\n")
  nodes
end

def traverse(node)
  node.link.each_with_index{|key,i|
    if $result[key].link.find{|k|k=="s"}
      if (node.cost - node.link_cost[i]) == $result[key].cost
        return [node.key, key, "s"]
      end
    else
      return [node.key].concat(traverse($result[key]))
    end
  }
  
end

node_data = {
  "s" => [["a", 5], ["b", 6], ["c", 2]],
  "a" => [["s", 5], ["b", 2], ["g", 6]],
  "b" => [["s", 6], ["a", 2], ["c", 3], ["d", 2]],
  "c" => [["s", 2], ["b", 3], ["d", 6]],
  "d" => [["b", 2], ["c", 6], ["g", 4]],
  "g" => [["a", 6], ["d", 4]],
}

puts "### dijstra"
$result = dijkstra(node_data)
puts traverse($result["g"]).reverse
$ ruby dijkstra.rb
### dijstra
#### initialize
(a, [s,b,g], [5,2,6], false, 100000000)
(b, [s,a,c,d], [6,2,3,2], false, 100000000)
(c, [s,b,d], [2,3,6], false, 100000000)
(d, [b,c,g], [2,6,4], false, 100000000)
(g, [a,d], [6,4], false, 100000000)
(s, [a,b,c], [5,6,2], false, 0)
#### calculated
(a, [s,b,g], [5,2,6], true, 5)
(b, [s,a,c,d], [6,2,3,2], true, 5)
(c, [s,b,d], [2,3,6], true, 2)
(d, [b,c,g], [2,6,4], true, 7)
(g, [a,d], [6,4], true, 11)
(s, [a,b,c], [5,6,2], true, 0)
s
a
g