code: def _create_matrix(self, document):
          
          sentences_as_words = [self._to_words_set(sent) for sent in document.sentences]
          sentences_count = len(sentences_as_words)
          weights = numpy.zeros((sentences_count, sentences_count))
  
          for i, words_i in enumerate(sentences_as_words):
              for j, words_j in enumerate(sentences_as_words):
                  weights[i, j] = self._rate_sentences_edge(words_i, words_j)
          weights /= weights.sum(axis=1)[:, numpy.newaxis]
  
          # In the original paper, the probability of randomly moving to any of the vertices
          # is NOT divided by the number of vertices. Here we do divide it so that the power
          # method works; without this division, the stationary probability blows up. This
          # should not affect the ranking of the vertices so we can use the resulting stationary
          # probability as is without any postprocessing.
          return numpy.full((sentences_count, sentences_count), (1.-self.damping) / sentences_count) \
              + self.damping * weights
docs: Create a stochastic matrix for TextRank.
  
          Element at row i and column j of the matrix corresponds to the similarity of sentence i
          and j, where the similarity is computed as the number of common words between them, divided
          by their sum of logarithm of their lengths. After such matrix is created, it is turned into
          a stochastic matrix by normalizing over columns i.e. making the columns sum to one. TextRank
          uses PageRank algorithm with damping, so a damping factor is incorporated as explained in
          TextRank's paper. The resulting matrix is a stochastic matrix ready for power method.