require "matrix" require "mathn" # 2006. 10. 5 # from http://www.freesearch.pe.kr # Ãß¼® ¿¬ÈޱⰣµ¿¾È ½É½ÉÇؼ­ ¸¸µé¾îº» PageRank ¾Ë°í¸®Áò ÀÔ´Ï´Ù. # ·çºñ·Î óÀ½ Â¥º¸´Â ÇÁ·Î±×·¥ÀÌ¶ó¼­ Á» °Å½Ã±â ÇÏÁö¸¸ ³ª¸§ Àß µ¹¾Æ°¡³×¿ä. # °øºÎÇϽô ºÐµé¿¡°Ô ¸¹Àº µµ¿òÀÌ µÇ±æ ¹Ù¶ø´Ï´Ù. class GooglePageRank def initialize(dim, alpha, epsilon) @dim = dim @epsilon = epsilon @noOfIter = 0 @alpha = alpha @HMatrix = nil @pi = nil @time = nil end def makeInitialPi #³ëµåÀÇ °¹¼ö·Î Á¤±ÔÈ­µÈ ·Î¿ì º¤Å͸¦ ¸¸µç´Ù. @pi0 = Matrix.column_vector([1/@dim] * @dim) end def makeSparseMatrix inputlist = Array.new() @dim.times do |count| print "#{count+1}¹ø° ³ëµåº¤ÅÍÀÇ outlink Á¤º¸ ÀÔ·Â(Àüü 3°³Àdzëµå Á¸Àç½Ã ¿¹ : 0,1,0) : " a = gets a.chop! inputlist[count] = a.split(/,\s*/) if a.split(/,\s*/).length == @dim retry if a.split(/,\s*/).length != @dim inputlist[count].collect! {|a| a.to_i} end #outlink°¡ Çϳªµµ ¾ø´Â°Íµé¿¡ ´ëÇÑ Á¤±ÔÈ­ ¼öÇàÀ» À§ÇÔ danglingNode = [] inputlist.each do |vector| noOfNum = 0 vector.each {|num| noOfNum += 1 if num > 0} if noOfNum == 0 danglingNode.push(1) else danglingNode.push(0) end next if noOfNum == 0 vector.collect! {|num| num / noOfNum if noOfNum != 0 } end @danglingnode = Matrix.column_vector(danglingNode) @HMatrix = Matrix.rows(inputlist) end def executePageRank @noOfIter = 0 residual = 1 pi = @pi0.dup yield @noOfIter, pi while residual >= @epsilon prevpi = pi @noOfIter += 1 #PageRank Power method pi = @alpha * pi.t * @HMatrix + ((@alpha * (pi.t * @danglingnode)[0,0] + (1.0 - @alpha)) * ((1/@dim) * Matrix.column_vector([1] * @dim).t )) pi = pi.t residual = (pi - prevpi).column_vectors()[0].r yield @noOfIter, pi end @pi = pi end def RankSort rankArray = @pi.column_vectors()[0].to_a rankHash = Hash.new() i = 1 rankArray.each{ |rank| rankHash[i] = rank i += 1 } rankArray = rankHash.sort {|x,y| y[1] <=> x[1] } yield rankArray end end #ÇÊ¿ä ÀÎÀÚ ÀÔ·Â #³ëµåÀÇ °¹¼ö¸¦ ÀÔ·Â ¹Þ´Â´Ù. print "ÃÑ ³ëµåÀÇ °¹¼ö¸¦ ÀԷ¹ٶ÷ : " noOfNode = gets.chop! if noOfNode.empty? or noOfNode.to_i == 0 puts "Á¤¼ö¸¦ ³Ö¾î Áֽñ⠹ٶø´Ï´Ù!" exit 1 end print "scaling Parameter¸¦ ÀÔ·Â ¹Ù¶÷(1~0 floatÇü) : " alpha = gets.chop! if alpha.empty? or alpha.to_f == 0.0 puts "float ÇüÀ¸·Î ³Ö¾î Áֽñ⠹ٶø´Ï´Ù!" exit 1 end print "Iteration Á¤¹Ðµµ¸¦ À§ÇÑ ÀÓ°è°ª ¼³Á¤(ÀÌÀü piº¤ÅÍ¿Í Çö piº¤ÅÍÀÇ À¯Å¬¸®µå¾ð °Å¸®) : " dist = gets.chop! if dist.empty? or dist.to_f == 0.0 puts "float ÇüÀ¸·Î ³Ö¾î Áֽñ⠹ٶø´Ï´Ù!" exit 1 end inputlist = Array.new() noOfNode = noOfNode.to_i alpha = alpha.to_f dist = dist.to_f PageRank = GooglePageRank.new(noOfNode, alpha, dist) #»ç¿ëÀÚ ÀÔ·ÂÀ¸·Î ¸µÅ© ¸ÞÆ®¸¯½º¸¦ ±¸Çö PageRank.makeSparseMatrix #Ãʱâ pi°ªÀ» ¸¸µé°í PageRank.makeInitialPi #ÀÓ°è°ªÀ» ±âÁØÀ¸·Î ÆäÀÌÁö ·©Å©¸¦ Iteration °è»êÇÑ´Ù. PageRank.executePageRank do |noOfIter, pi| if noOfIter == 0 puts "Ãʱâ PageRank Vector : " + pi.to_s elsif noOfIter > 0 puts "\n\n#{noOfIter} ¹ø° ¹Ýº¹" puts "°»½ÅµÈ PageRank Vector : \n#{pi.to_s}\n" end end PageRank.RankSort do |RankArray| puts "\n\nPageRank Result!\n\n" RankArray.each{|rank| puts rank[0].to_s + "¹ø ³ëµå \nscore : " + rank[1].to_s + "\n"} end