Rubyで幅優先探索による有向グラフの距離

ノード間距離が1である有向グラフにおいて、あるノードまでの最短距離を調べるプログラム。
終点となるノードは、@search_wordで与えられる(このプログラムではentityとなっている)。
因数に与えるファイルの形式は、

リンク元\tリンク先\tリンク先\t・・・

を各行に配置したもの。
出力はリダイレクトで他のファイルに出力する。
STDERR.printにより、ファイル出力以外の情報は、シェルに出力される。



#幅優先探索によってノード間最短距離を求める
#有向グラフで末端のものから辿る
 
class BFS
  def initialize
    @word = Hash.new   # word list
    @all_num = Hash.new   # word number
    File.open(ARGV[0]){|file|
      i = 0
      while text = file.gets do
        text = text.chomp!.split("\t")
        inode = text.shift
        text.each do |onode|
          @word[onode] = Array.new if @word[onode] == nil
          @word[onode].push inode
        end
      end
    }
    @length = Hash.new
    @searched = Hash.new
    @search_word = "entity"   # 終端となるノード
  end
  def main
    i = 1
    search_list = search(i, @search_word)
    STDERR.print i, "\n"
    until search_list.length == 0 do
      i += 1
      tmp_list = Array.new
      search_list.each do |sl|
        next if @searched[sl] == true
        tmp_list.push search(i, sl) unless @word[sl] == nil
      end
      break if tmp_list.flatten! == nil
      STDERR.print i, "\n"
      search_list = tmp_list.uniq
    end
  end
  def search(l, to_word)
    from_word = @word[to_word]
    @searched[to_word] = true
    from_word.each do |w|
      @length[w] = l if @length[w] == nil
    end
    return from_word
  end
  def lprint
    l_size = Array.new   # 同じ深さのものの数を調べる配列
    @length.each do |k, v|
      print k, " ", v, "\n"
      l_size[v] = 0 if l_size[v] == nil
      l_size[v] += 1
    end
    STDERR.print @search_word, "から\n"
    for i in 1..(l_size.length-1) do
      STDERR.print "深さ", i, ":", l_size[i], "\n"
    end
  end
end
 
a = BFS.new
a.main
a.lprint
 
最終更新:2008年09月21日 14:48
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。