SimRank

SimRank is a recursive similarity measure where nodes are considered similar if they are connected to similar others. The following implementation covers the generalized version proposed by Zhao et al. (2009).

References

  • Jeh, G., & Widom, J. (2002). SimRank: a measure of structural-context similarity. Proceedings of the 8th ACM SIGKDD international conference on Knowledge discovery and data mining, 538-543.
  • Zhao, P., Han, J., & Sun, Y. (2009). P-Rank: a comprehensive structural similarity measure over information networks. Proceedings of the 18th ACM conference on Information and knowledge management, 553-562.
SimRank <- function(w, alpha = 0.8, beta = 1) {
  do <- rowSums(w) 
  di <- colSums(w) 
  n <- nrow(w) 
  z <- diag(1, n, n)
  rownames(z) <- rownames(w)
  colnames(z) <- colnames(w)
  onei <- apply(w, 1, function(x) which(x == 1), simplify = FALSE)
  inei <- apply(w, 2, function(x) which(x == 1), simplify = FALSE)
  delta <- 1
  while (delta > 1e-10) {
    z.o <- z
    for (i in 1:n) {
      for (j in 1:n) {
        if (i == j) next
        min.di <- min(di[i], di[j])
        min.do <- min(do[i], do[j])
        if (min.di != 0 & min.do != 0) {
          a <- alpha / (di[i] * di[j])
          b <- sum(as.matrix(z.o[inei[[i]], inei[[j]]]))
          c <- alpha / (do[i] * do[j])
          d <- sum(as.matrix(z.o[onei[[i]], onei[[j]]]))
          z[i, j] <- beta * a * b + (1 - beta) * c * d
        }
        if (min.di != 0 & min.do == 0) {
          a <- alpha / (di[i] * di[j])
          b <- sum(as.matrix(z.o[inei[[i]], inei[[j]]]))
          z[i, j] <- beta * a * b
        }
        if (min.di == 0 & min.do != 0) {
          c <- alpha / (do[i] * do[j])
          d <- sum(as.matrix(z.o[onei[[i]], onei[[j]]]))
          z[i, j] <- (1 - beta) * c * d
        }
      }
    }
    delta <- abs(sum(abs(z)) - sum(abs(z.o)))
  }
  return(z)
}