はじめに
前回の記事を投稿後、Ruby版networkxがあったので、更にやってみた。
問題の整理[再掲]
ノード数N
の有向グラフがある。
高橋くんはノード1からスタートして100回ランダムな遷移を行います。
遷移後、高橋くんがどのノードにいるかを答えてください。
入力
N M
A1 B1
.
.
.
Am Bm
入力例
5 7
1 2
1 3
2 4
3 4
3 5
4 5
5 1
Ruby版networkx
require_relative './networkx_graph'
require_relative './networkx_pagerank'
n, m = gets.split.map(&:to_i)
g = NetworkX::Graph.new
m.times do
a, b = gets.split.map(&:to_i)
g.add_edge(a - 1, b - 1)
end
v = n.times.map{ rand(0...1.0) }
vs = v.sum
v = n.times.map{ |i| [i, v[i] / vs] }.to_h
puts NetworkX.pagerank(g, v, 0.95)
# output
0.2141053207395146
0.14561400379973355
0.21308767736061818
0.2141053207395146
0.21308767736061818
ぐぬぬ、値が違う。
原因追究
graph.rb
def add_edge(node_1, node_2, **edge_attrs)
add_node(node_1)
add_node(node_2)
edge_attrs = (@adj[node_1][node_2] || {}).merge(edge_attrs)
@adj[node_1][node_2] = edge_attrs
@adj[node_2][node_1] = edge_attrs # 問題の行
end
最後の@adj[node_2][node_1] = edge_attrs
をコメントアウトしたら、それらしい数値になりました。
恐らく、この行で有向グラフから無向グラフになっていると考えられます。
追記
よくよく見ると
class | グラフ種別 |
---|---|
NetworkX::Graph | 無向グラフ |
NetworkX::DiGraph | 有効グラフ |
NetworkX::MultiGraph | マルチ無向グラフ |
NetworkX::MultiDiGraph | マルチ有向グラフ |
とあり、今回はDiGraph
を使用するのが正しいです。
修正.rb
require_relative './networkx_graph'
require_relative './networkx_digraph'
require_relative './networkx_pagerank'
n, m = gets.split.map(&:to_i)
g = NetworkX::DiGraph.new # 有向グラフ
m.times do
a, b = gets.split.map(&:to_i)
g.add_edge(a - 1, b - 1)
end
v = n.times.map { |i| [i, 1.0 / n] }.to_h # 乱数でなくてもよくね
puts NetworkX.pagerank(g, v, 0.95)
また、初期値はどうせ収束するし乱数でなくてもよさそうです。
まとめ
- pegerank に更に詳しくなった