text: # -*- coding: utf-8 -*-
  from __future__ import unicode_literals
  
  class TextRank(object):
      def __init__(self, weight):
          self.D = len(weight[0])
          self.d = 0.85
          self.max_iter = 200
          self.min_diff = 0.00001
          self.top = []
  
          self.weight = weight
          self.weight_sum = [sum(w) for w in weight]
          self.vertex = [1.0]*self.D
  
      def solve(self):
          for _ in range(self.max_iter):
              m = []
              max_diff = 0
              for i in range(self.D):
                  m.append(1-self.d)
                  for j in range(self.D):
                      if j == i or self.weight_sum[j] == 0:
                          continue
                      m[-1] += (self.d*self.weight[i][j]
                                / self.weight_sum[j]*self.vertex[j])
                  if abs(m[-1] - self.vertex[i]) > max_diff:
                      max_diff = abs(m[-1] - self.vertex[i])
              self.vertex = m
              if max_diff <= self.min_diff:
                  break
          self.top = list(enumerate(self.vertex))
          self.top = sorted(self.top, key=lambda x: x[1], reverse=True)
  
      def top_index(self, limit):
          return list(map(lambda x: x[0], self.top))[:limit]
  
  
  class KeywordTextRank(object):
  
      def __init__(self, docs):
          self.docs = docs
          self.words = {}
          self.vertex = {}
          self.d = 0.85
          self.max_iter = 200
          self.min_diff = 0.001
          self.top = []
  
      def solve(self):
          for doc in self.docs:
              que = []
              for word in doc:
                  if word not in self.words:
                      self.words[word] = set()
                      self.vertex[word] = 1.0
                  que.append(word)
                  if len(que) > 5:
                      que.pop(0)
                  for w1 in que:
                      for w2 in que:
                          if w1 == w2:
                              continue
                          self.words[w1].add(w2)
                          self.words[w2].add(w1)
          for _ in range(self.max_iter):
              m = {}
              max_diff = 0
              for k, v in self.words.items():
                  m[k] = 1-self.d
                  for j in v:
                      if k == j or len(self.words[j]) == 0:
                          continue
                      m[k] += (self.d/len(self.words[j])*self.vertex[j])
                  if abs(m[k] - self.vertex[k]) > max_diff:
                      max_diff = abs(m[k] - self.vertex[k])
              self.vertex = m
              if max_diff <= self.min_diff:
                  break
          self.top = list(self.vertex.items())
          self.top = sorted(self.top, key=lambda x: x[1], reverse=True)
  
      def top_index(self, limit):
          return list(map(lambda x: x[0], self.top))[:limit]
  
      def top(self, limit):
          return list(map(lambda x: self.docs[x[0]], self.top))
  
  